Quartz与Spring的整合-Quartz中的job如何自动注入spring容器托管的对象

教程分享 > Java教程 > Spring (1441) 2024-08-07 11:05:25
我们要达到这样的效果
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以后进行属性注入。
 
https://www.leftso.com/article/15.html

相关文章
Spring Boot 2.0是spring boot项目的最新版本,这里讲讲解整合Quartz Job实现任务调度增强功能。向QuartzJobBean注入Spring Boot 2.0 的S...
学习配置Quartz调度程序以运行使用Spring启动Java配置配置的Spring批处理作业。虽然,Spring的默认调度程序也很好,但是quartz可以更好地以更可配置的方式调度和调用任务。...
Spring框架Spring IoC容器的核心原理,前三篇已经从历史的角度和大家一起探讨了为什么会有Spring,Spring的两个核心概念:IoC和AOP的雏形,Spring的历史变迁和如今的...
在 Spring 框架中,在配置文件中声明 bean 依赖项是一个很好的做法,因此 Spring 容器能够自动装配协作 bean 之间的关系。这意味着可以通过检查BeanFactory的内容让 ...
spring boot mybatis 整合使用讲解介绍,spring boot与MyBatis的使用讲解介绍。spring boot mybatis xml mapper方式的入门和通过一个简...
Java编程中spring boot项目如何获取spring容器applicationContext
Spring Context 与Spring MVC Context那些坑
在 Spring 框架中,按名称自动装配 bean 允许对属性进行自动装配,这样它将检查容器并查找名称与需要自动装配的属性完全相同的 bean。例如,如果您有一个按名称设置为自动装配的 bean...
在 Spring 框架中,通过构造函数自动装配 bean类似于byType,但适用于构造函数参数。在启用自动装配的 bean 中,它查找构造函数参数的类类型,然后按类型对所有构造函数参数执行自动...
Java编程中Spring Boot整合RabbitMQ实现消息中间件RabbitMQ的使用
Spring框架每个版本的特性及历史介绍,从Spring框架开始1.0到最新的Spring 5.0进行讲解整个Spring生涯中的演变过程以及spring框架生态的扩展。
spring boot 入门之整合spring session实现session共享。一直以来Java编程中web项目中的session共享问题都是一个很难解决的问题。接下来将讲解通过sprin...
spring data redis设置缓存的过期时间,spring data redis更新缓存的过期时间
引言    通过之前spring boot mybatis 整合的讲解: spring boot mybaties整合  (spring boot mybaties 整合 基于Java注解方式写...