Java下Spring实现Quartz集群分布式(二)

一、序言

上篇文章Java下Spring实现Quartz集群分布式(一)的spring管理配置的xml文件的解析之一,为何需要配置红色字体的属性呢?

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
 
    <bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <!--<property name="applicationContextSchedulerContextKey" value="applicationContext"/>-->
        <property name="jobFactory">
            <bean class="wade.core.interceptors.SpringBeanJobFactory"/>
        </property>

        <property name="dataSource">
            <ref bean="dataSource"/>
        </property>
        <property name="configLocation" value="classpath:/conf/quartz.properties"/>
    </bean>
 
</beans>

二、正文

1、假设我们要实现以下代码,即spring注入。

public class Task implements Job {
    @Autowired
    private AppServcie appServcie ;

    @Override
    public void execute(JobExecutionContext ctx) throws JobExecutionException {
        ...
}

2、但是Job对象的实例化过程是在Quartz中进行的,AppServcie是在Spring容器当中的,那么如何将他们关联到一起呢。好在Quartz提供了JobFactory接口,让我们可以自定义实现创建Job的逻辑。 

public interface JobFactory {

    Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException;

}

3、 那么我们通过实现JobFactory 接口,在实例化Job以后,在通过ApplicationContext 将Job所需要的属性注入即可。在Spring与Quartz集成时 用到的是org.springframework.scheduling.quartz.SchedulerFactoryBean这个类。源码如下,我们只看最关键的地方。


        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);
            }
        }

4、其中红色标记的是重点,如果我们不指定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.");
        }
    }

}

5、其他的我们都不管,我们就看红色的地方,这里是创建了一个Job,那我们就在这里去给Job的属性进行注入就可以了,让我们写一个类继承它,然后复写这个方法进行对Job的注入。

package wade.core.interceptors;

import org.quartz.spi.TriggerFiredBundle;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.AdaptableJobFactory;

/**
 * <P><B>描述:</B> 自定义SpringBeanJobFactory,用于对Job注入ApplicationContext等。 </P>
 *
 * 
 */
public class SpringBeanJobFactory extends AdaptableJobFactory {
    /**
     * The Application context.
     *
     * @see ApplicationContext
     */
    private ApplicationContext applicationContext;
    /**
     * The Capable bean factory.
     */
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;
    /**
     * 日志记录.
     */
    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(SpringBeanJobFactory.class);

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        LOGGER.info("创建作业实体类");
        //调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        //进行注入(这属于Spring的技术,不清楚的可以查看Spring的API)
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}
 

6、接着就是最开始的配置到spring里 。

<property name="jobFactory">
            <bean class="wade.core.interceptors.SpringBeanJobFactory"/>
</property>

猜你喜欢

转载自blog.csdn.net/zengwende/article/details/87734578