1. 程式人生 > >Quartz中擴充套件MethodInvokingJobDetailFactoryBean實現對任務排程的攔截

Quartz中擴充套件MethodInvokingJobDetailFactoryBean實現對任務排程的攔截

利用Quartz來實現對任務的排程已經被廣泛地應用了,一個利用Quartz來進行任務排程的典型配置如下:

若有多個任務需要排程,則配置多個JobDetail、Trigger即可,待執行的Task bean沒有啥任何要求,不需要extends任何class、或者implements任何interface,只是被執行的method需要是無引數的;

但是在我們現實專案中,僅僅完成這樣的功能是還不夠的,我們還需要爭取完成以下幾點:

  1. 對所有的Task實現執行開始、結束時間的記錄;
  2. 對每天的Task執行結果持久化、或者通過email、旺旺訊息等方式告知相關owner;
  3. 當我們有多臺Task伺服器時,如何保證每個任務只在一臺伺服器上執行;

針對以上幾個問題,我們也都有很簡單、直接的辦法可以搞定,比如說1、2兩點可以直接在每個任務中各自編碼完成,但是這樣不僅每個task都要寫非常類似的重複程式碼、而且不能保證每個任務的執行情況都被記錄,因為某些task的編碼人員就不會在意這些非功能性需求;對於第3點,我們也可以通過配置來完成向不同task伺服器部署不一樣的釋出包來完成,但這給釋出帶來了麻煩,這意味著有多少臺task伺服器,就需要通過修改配置重新打包併發布多少次;

其實我們可以利用Spring預設提供的AOP來非常優雅的解決這幾個問題:擴充套件MethodInvokingJobDetailFactoryBean來實現對任務排程時的攔截!其關鍵程式碼為MethodInvokingJobDetailFactoryBean.MethodInvokingJob.executeInternal(JobExecutionContext context);這個method中;

具體步驟如下:

  1. 新增所有Task都需要實現的interface,可參考如下程式碼:
  2. 基於MethodInvokingJobDetailFactoryBean實現自定義的JobDetailFactoryBean,在具體執行待排程任務的method前後加入公用邏輯,比如記錄開始、結束日期、判斷該task是否由該臺伺服器執行、任務執行完成之後將執行結果進行持久化或者發email等給相關owner;可參考如下程式碼:
  3. 將自定義JobDetailFactoryBean的bean配置設定為abstract,從而減少每個task的相關配置量,新的程式碼可參考如下配置: