zoukankan      html  css  js  c++  java
  • Quartz的Job注入到Spring容器的实现过程

    需要导入的pom

    <!-- quartz -->
    <dependency>
       <groupId>org.quartz-scheduler</groupId>
       <artifactId>quartz</artifactId>
    </dependency>

    我想达到这样的效果

    1.构建自定义Job,执行定时任务

    //构建job信息
    JobDetail jobDetail = JobBuilder
             .newJob(ExecutionJob.class)
             .withIdentity(JOB_NAME + quartzJob.getId())
             .build();
    
    //通过触发器名和cron 表达式创建 Trigger
    Trigger cronTrigger = newTrigger()
             .withIdentity(JOB_NAME + quartzJob.getId())
             .startNow()
             .withSchedule(CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression()))
             .build();
    cronTrigger.getJobDataMap().put(QuartzJob.JOB_KEY, quartzJob);

    //将jobtrigger加入Scheduler

    scheduler.scheduleJob(jobDetail, cronTrigger);

    2.自定义ExecutionJob

    @Async
    @SuppressWarnings({"unchecked", "all"})

    public class ExecutionJob implements Job {
    @Override public void execute(JobExecutionContext context) throws JobExecutionException { ...... } }

    但是Job对象的实例化过程是在Quartz中进行的,ExecutionJob是在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这个类。
    源码如下,只看红色最关键的代码即可:

    private Scheduler prepareScheduler(SchedulerFactory schedulerFactory) throws SchedulerException {
            ........
    // Get Scheduler instance from SchedulerFactory. try { Scheduler scheduler = createScheduler(schedulerFactory, this.schedulerName); populateSchedulerContext(scheduler); if (!this.jobFactorySet && !(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.applicationContext != null && this.jobFactory instanceof ApplicationContextAware) { ((ApplicationContextAware) this.jobFactory).setApplicationContext(this.applicationContext); } if (this.jobFactory instanceof SchedulerContextAware) { ((SchedulerContextAware) this.jobFactory).setSchedulerContext(scheduler.getContext()); } scheduler.setJobFactory(this.jobFactory); } return scheduler; }
    .......
    }

    意思是:如果我们不指定jobFactory,那么Spring就使用AdaptableJobFactory

    再来看一下AdaptableJobFactory这个类的实现

    package org.springframework.scheduling.quartz;
    
    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 {
        @Override
        public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException {
            try {
                Object jobObject = createJobInstance(bundle);
                return adaptJob(jobObject);
            }
            catch (Throwable ex) {
                throw new SchedulerException("Job instantiation failed", ex);
            }
        }
    
        protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
            Class<?> jobClass = bundle.getJobDetail().getJobClass();
            return ReflectionUtils.accessibleConstructor(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.");
            }
        }
    }

    可以看见createJobInstance方法实例化了Job,但我想把Job注入到Spring中。

    所以需要写一个类继承AdaptableJobFactory,然后重写createJobInstance方法实现对Job的注入。

        @Component("quartzJobFactory")
        public static class QuartzJobFactory extends AdaptableJobFactory {
    
            private final AutowireCapableBeanFactory capableBeanFactory;
    
            public QuartzJobFactory(AutowireCapableBeanFactory capableBeanFactory) {
                this.capableBeanFactory = capableBeanFactory;
            }
    
            @Override
            protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
                //调用父类的方法,把Job注入到spring中
                Object jobInstance = super.createJobInstance(bundle);
                capableBeanFactory.autowireBean(jobInstance);
                return jobInstance;
            }
        }

    接下来set我的Job到JobFactory里,通过scheduler.start()开启定时器。

        /**
         * 注入scheduler到spring
         *
         * @param quartzJobFactory
         * @return Scheduler
         * @throws Exception
         */
        @Bean(name = "scheduler")
        public Scheduler scheduler(QuartzJobFactory quartzJobFactory) throws Exception {
            SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
            factoryBean.setJobFactory(quartzJobFactory);
            factoryBean.afterPropertiesSet();
            Scheduler scheduler = factoryBean.getScheduler();
            scheduler.start();
            return scheduler;
        }

    这样就完成了Job注入到Spring的功能,

    原理就是扩展JobFactory创建Job的方法,启动Scheduler之后将Scheduler注入到Spring。

    代码地址:https://github.com/SuPiaoPiao/spring_quartz.git

  • 相关阅读:
    strcpy
    Apple Swift中英文开发资源集锦[apple swift resources]
    c/c++指针总结[pointer summary]
    TestPointer
    66. 有序数组构造二叉搜索树[array to binary search tree]
    HDU 2112 HDU Today
    HDU 3790 最短路径问题
    HDU 2544 最短路
    模拟赛 Problem 3 经营与开发(exploit.cpp/c/pas)
    模拟赛 Problem 2 不等数列(num.cpp/c/pas)
  • 原文地址:https://www.cnblogs.com/supiaopiao/p/14953978.html
Copyright © 2011-2022 走看看