Quartz與Spring集成 Job如何自動注入Spring容器託管的對象

 

在Spring中使用Quartz有兩種方式實現:
第一種是任務類繼承QuartzJobBean,
第二種則是在配置文件裏定義任務類和要執行的方法,類和方法能夠是普通類。很顯然,第二種方式遠比第一種方式來的靈活。html

 

測試環境 Spring3 M2 quartz-2.1.7

咱們要達到這樣的效果

複製代碼
public class CancelUnpaidOrderTask implements Job {
    @Autowired
    private AppOrderService orderService;

    @Override
    public void execute(JobExecutionContext ctx) throws JobExecutionException {
        ...
}
複製代碼

可是Job對象的實例化過程是在Quartz中進行的,AppOrderService是在Spring容器當中的,那麼如何將他們關聯到一塊兒呢。好在Quartz提供了JobFactory接口,讓咱們能夠自定義實現建立Job的邏輯。

public interface JobFactory {
Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException;
}

那麼咱們經過實現JobFactory 接口,在實例化Job之後,在經過ApplicationContext 將Job所須要的屬性注入便可

在Spring與Quartz集成時 用到的是org.springframework.scheduling.quartz.SchedulerFactoryBean這個類。源碼以下,咱們只看最關鍵的地方。

複製代碼
        // Get Scheduler instance from SchedulerFactory.
        try {
            this.scheduler = createScheduler(schedulerFactory, this.schedulerName);
            populateSchedulerContext();

            if (!this.jobFactorySet && !(this.scheduler instanceof RemoteScheduler)) {
                // Use AdaptableJobFactory as default for a local Scheduler, unless when
                // explicitly given a null value through the "jobFactory" bean property.
                this.jobFactory = new AdaptableJobFactory();
            }
            if (this.jobFactory != null) {
                if (this.jobFactory instanceof SchedulerContextAware) {
                    ((SchedulerContextAware) this.jobFactory).setSchedulerContext(this.scheduler.getContext());
                }
                this.scheduler.setJobFactory(this.jobFactory);
            }
        }
複製代碼

其中紅色標記的是重點,若是咱們不指定jobFactory,那麼Spring就使用AdaptableJobFactory。咱們在來看一下這個類的實現

複製代碼
package org.springframework.scheduling.quartz;

import java.lang.reflect.Method;

import org.quartz.Job;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;

import org.springframework.util.ReflectionUtils;


public class AdaptableJobFactory implements JobFactory {

   
    public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException {
        return newJob(bundle);
    }

    public Job newJob(TriggerFiredBundle bundle) throws SchedulerException {
        try {
            Object jobObject = createJobInstance(bundle);
            return adaptJob(jobObject);
        }
        catch (Exception ex) {
            throw new SchedulerException("Job instantiation failed", ex);
        }
    }

    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        // Reflectively adapting to differences between Quartz 1.x and Quartz 2.0...
        Method getJobDetail = bundle.getClass().getMethod("getJobDetail");
        Object jobDetail = ReflectionUtils.invokeMethod(getJobDetail, bundle);
        Method getJobClass = jobDetail.getClass().getMethod("getJobClass");
        Class jobClass = (Class) ReflectionUtils.invokeMethod(getJobClass, jobDetail);
        return jobClass.newInstance();
    }

    protected Job adaptJob(Object jobObject) throws Exception {
        if (jobObject instanceof Job) {
            return (Job) jobObject;
        }
        else if (jobObject instanceof Runnable) {
            return new DelegatingJob((Runnable) jobObject);
        }
        else {
            throw new IllegalArgumentException("Unable to execute job class [" + jobObject.getClass().getName() +
                    "]: only [org.quartz.Job] and [java.lang.Runnable] supported.");
        }
    }

}
複製代碼

其餘的咱們都無論,咱們就看紅色的地方,這裏是建立了一個Job,那咱們就在這裏去給Job的屬性進行注入就能夠了,讓咱們寫一個類繼承它,而後複寫這個方法進行對Job的注入。

複製代碼
public class MyJobFactory extends AdaptableJobFactory {

    //這個對象Spring會幫咱們自動注入進來,也屬於Spring技術範疇.
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;
    
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        //調用父類的方法
        Object jobInstance = super.createJobInstance(bundle);
        //進行注入,這屬於Spring的技術,不清楚的能夠查看Spring的API.
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}
複製代碼

接下來把他配置到Spring當中去

<bean id="jobFactory" class="com.gary.operation.jobdemo.demo1.MyJobFactory"></bean>

而後在把org.springframework.scheduling.quartz.SchedulerFactoryBean的jobFactory設置成咱們本身的。

<bean name="MyScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
  <!-- 其餘屬性省略 -->   <property name="jobFactory" ref="jobFactory"></property> </bean>

這樣就完成了Spring對Job的注入功能,其實很簡單,原理就是在咱們擴展JobFactory建立job的方法,在建立完Job之後進行屬性注入。

http://www.cnblogs.com/daxin/p/3608320.htmljava

https://github.com/helloworldtang/ch6_2_3/tree/master/src/main/java/com/schedule/quartzgit

http://my.oschina.net/hhaijun/blog/698498github

http://blog.csdn.net/fenglibing/article/details/6847158
http://blog.csdn.net/whaosy/article/details/6298686spring

相關文章
相關標籤/搜索