zoukankan      html  css  js  c++  java
  • Quartz与Spring集成 Job如何自动注入Spring容器托管的对象

     

    在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当中去

    <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.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

  • 相关阅读:
    POJ 1681 Painter's Problem(高斯消元法)
    HDU 3530 Subsequence(单调队列)
    HDU 4302 Holedox Eating(优先队列或者线段树)
    POJ 2947 Widget Factory(高斯消元法,解模线性方程组)
    HDU 3635 Dragon Balls(并查集)
    HDU 4301 Divide Chocolate(找规律,DP)
    POJ 1753 Flip Game(高斯消元)
    POJ 3185 The Water Bowls(高斯消元)
    克琳:http://liyu.eu5.org
    WinDbg使用
  • 原文地址:https://www.cnblogs.com/softidea/p/5867014.html
Copyright © 2011-2022 走看看