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

  • 相关阅读:
    翻译连载 |《你不知道的JS》姊妹篇 |《JavaScript 轻量级函数式编程》 第 6 章:值的不可变性
    翻译 | 带你秒懂内存管理 第一部(共三部)
    基于 Electron 的爬虫框架 Nightmare
    微信小程序教学第三章(含视频):小程序中级实战教程:列表静态页面制作
    翻译 | 使用AFrame打造WebVR版《我的世界》
    微信小程序教学第三章第三节(含视频):小程序中级实战教程:视图与数据关联
    翻译 | 玩转 React 表单 —— 受控组件详解
    翻译连载 |《你不知道的JS》姊妹篇 |《JavaScript 轻量级函数式编程》 第 5 章:减少副作用
    翻译连载 |《你不知道的JS》姊妹篇 |《JavaScript 轻量级函数式编程》 第 2 章:函数基础
    一张图告诉你移动Web前端所有技术(工程化、预编译、自动化)
  • 原文地址:https://www.cnblogs.com/softidea/p/5867014.html
Copyright © 2011-2022 走看看