1. 程式人生 > 其它 >quartz的實現流程

quartz的實現流程

需要匯入的pom

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

我想達到這樣的效果

public class ExecutionJobTask implements Job {
    @Autowired
    private QuartzJobService quartzJobService;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
//執行我的方法
quartzJobService
.xxx(); ...... } }

但是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這個類。
原始碼如下,我們只看紅色最關鍵的程式碼

private Scheduler prepareScheduler(SchedulerFactory schedulerFactory) throws SchedulerException {
        if (this.resourceLoader != null) {
            // Make given ResourceLoader available for SchedulerFactory configuration.
configTimeResourceLoaderHolder.set(this.resourceLoader); } if (this.taskExecutor != null) { // Make given TaskExecutor available for SchedulerFactory configuration. configTimeTaskExecutorHolder.set(this.taskExecutor); } if (this.dataSource != null) { // Make given DataSource available for SchedulerFactory configuration. configTimeDataSourceHolder.set(this.dataSource); } if (this.nonTransactionalDataSource != null) { // Make given non-transactional DataSource available for SchedulerFactory configuration. configTimeNonTransactionalDataSourceHolder.set(this.nonTransactionalDataSource); } // 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; } finally { if (this.resourceLoader != null) { configTimeResourceLoaderHolder.remove(); } if (this.taskExecutor != null) { configTimeTaskExecutorHolder.remove(); } if (this.dataSource != null) { configTimeDataSourceHolder.remove(); } if (this.nonTransactionalDataSource != null) { configTimeNonTransactionalDataSourceHolder.remove(); } } }

意思是說:如果我們不指定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方法例項化了JobClass,但我想把JobClass注入到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;
        }
    }

接下來注入我自己的Job到JobFactory裡

    /**
     * 注入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的方法,在建立完Job以後進行屬性注入。