在Spring中使用Quartz有两种方式实现:
第一种是任务类继承QuartzJobBean,
第二种则是在配置文件里定义任务类和要执行的方法,类和方法可以是普通类。很显然,第二种方式远比第一种方式来的灵活。
测试环境 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当中去
然后在把org.springframework.scheduling.quartz.SchedulerFactoryBean的jobFactory设置成我们自己的。
这样就完成了Spring对Job的注入功能,其实很简单,原理就是在我们扩展JobFactory创建job的方法,在创建完Job以后进行属性注入。
http://www.cnblogs.com/daxin/p/3608320.html
https://github.com/helloworldtang/ch6_2_3/tree/master/src/main/java/com/schedule/quartz
http://my.oschina.net/hhaijun/blog/698498
http://blog.csdn.net/fenglibing/article/details/6847158
http://blog.csdn.net/whaosy/article/details/6298686