springboot 整合 quartz 配置定时任务

springboot 整合 quartz 配置定时任务

    • 1 quartz 的基本使用
      • 1.1 引入依赖
      • 1.2 任务class
      • 1.3 测试类
    • 2 springboot 整合 quartz
      • 2.1 引入依赖
      • 2.2 quartz 配置类
        • 2.2.1 方式一(简单的 Trigger)
        • 2.2.2 方式二(cron 表达式)
      • 2 .3 启动类添加注解 **@EnableScheduling**
    • 3 springboot 整合 quartz 调用 service 方法
      • 3.1 当调用 service 方法时出现 `java.lang.NullPointerException`
      • 3.2 解决方案
      • 3.3代码实现
        • 3.3.1 方式一——普通的继承方式
        • 3.3.2 方式二——使用内部类继承

1 quartz 的基本使用

1.1 引入依赖

<dependency>
   <groupId>org.quartz-schedulergroupId>
   <artifactId>quartzartifactId>
   <version>2.3.2version>
dependency>

1.2 任务class

@Slf4j
public class QuartzTask implements Job {
   @Override
   public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
      log.info(new Date() + "");
   }
}

1.3 测试类

public class Test {
   public static void main(String[] args) throws SchedulerException {
      // 1 创建 job 对象
      JobDetail job = JobBuilder.newJob(QuartzTask.class).build();

      // 2 创建 trigger 对象
//    Trigger trigger = TriggerBuilder.newTrigger().withSchedule(SimpleScheduleBuilder.repeatSecondlyForever()).build();
      Trigger trigger = TriggerBuilder.newTrigger().withSchedule(CronScheduleBuilder.cronSchedule("*/2 * * * * ?")).build();

      // 3 创建 scheduler 对象
      Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
      scheduler.scheduleJob(job,trigger);

      // 4 启动
      scheduler.start();
   }
}

2 springboot 整合 quartz

2.1 引入依赖

<dependency>
   <groupId>org.quartz-schedulergroupId>
   <artifactId>quartzartifactId>
   <version>2.3.2version>
dependency>
<dependency>
   <groupId>org.springframeworkgroupId>
   <artifactId>spring-context-supportartifactId>
dependency>
<dependency>
   <groupId>org.springframeworkgroupId>
   <artifactId>spring-txartifactId>
dependency>

2.2 quartz 配置类

2.2.1 方式一(简单的 Trigger)

@Configuration
public class QuartzConfig {

   // 1 创建 job 对象
   @Bean
   public JobDetailFactoryBean jobDetailFactoryBean(){
      JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
      jobDetailFactoryBean.setJobClass(SpringbootQuartzTask.class);
      return jobDetailFactoryBean;
   }

   // 2 创建 trigger 对象
   @Bean
   public SimpleTriggerFactoryBean simpleTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
      SimpleTriggerFactoryBean simpleTriggerFactoryBean = new SimpleTriggerFactoryBean();
      simpleTriggerFactoryBean.setJobDetail(jobDetailFactoryBean.getObject());
      simpleTriggerFactoryBean.setRepeatInterval(2000);
      return simpleTriggerFactoryBean;
   }
   // 3 创建 scheduler 对象
   @Bean
   public SchedulerFactoryBean schedulerFactoryBean(SimpleTriggerFactoryBean simpleTriggerFactoryBean){
      SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
      schedulerFactoryBean.setTriggers(simpleTriggerFactoryBean.getObject());
      return schedulerFactoryBean;
   }

}

2.2.2 方式二(cron 表达式)

@Configuration
public class QuartzConfig {

   // 1 创建 job 对象
   @Bean
   public JobDetailFactoryBean jobDetailFactoryBean(){
      JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
      jobDetailFactoryBean.setJobClass(SpringbootQuartzTask.class);
      return jobDetailFactoryBean;
   }

   // 2 创建 trigger 对象
   @Bean
   public  CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
      CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
      cronTriggerFactoryBean.setJobDetail(jobDetailFactoryBean.getObject());
      cronTriggerFactoryBean.setCronExpression("*/2 * * * * ?");
      return cronTriggerFactoryBean;
   }
   // 3 创建 scheduler 对象
   @Bean
   public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBean){
      SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
      schedulerFactoryBean.setTriggers(cronTriggerFactoryBean.getObject());
      return schedulerFactoryBean;
   }
}

2 .3 启动类添加注解 @EnableScheduling

@EnableScheduling
@SpringBootApplication
public class SpringbootTaskApplication {
   public static void main(String[] args) {
      SpringApplication.run(SpringbootTaskApplication.class, args);
   }
}

3 springboot 整合 quartz 调用 service 方法

3.1 当调用 service 方法时出现 java.lang.NullPointerException

如果按照上面的方法,在 job 类中调用 service 中的方法,会出现java.lang.NullPointerException: null错误。

这是因为在实例化 job 类时并没有由 spring 处理,而是由 AdaptableJobFactory 类中的 protected Object createJobInstance(TriggerFiredBundle bundle) 通过反射创建的,所以 spring 的 ioc 容器中就没有 job 的实例。因此,service 的实例就无法注入。调用会出现空指针。

注入的与被注入的对象都要被 spring 管理才能完成注入。

部分源码

protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
   Class<?> jobClass = bundle.getJobDetail().getJobClass();
   return ReflectionUtils.accessibleConstructor(jobClass).newInstance();
}

3.2 解决方案

可以自己编写一个类,继承 AdaptableJobFactory,然后重写 createJobInstance 方法。将创建的实例对象手动添加到 IOC 容器中,完成注入。

3.3代码实现

3.3.1 方式一——普通的继承方式

  1. 重写 AdaptableJobFactory 中的 createJobInstance 方法
package com.example.demo;

import org.quartz.spi.TriggerFiredBundle;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;

@Component
public class MyAdaptableJobFactory extends AdaptableJobFactory {

   @Autowired
   private AutowireCapableBeanFactory autowireCapableBeanFactory;

   @Override
   protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
      Object object = super.createJobInstance(bundle);
      autowireCapableBeanFactory.autowireBean(object);
      return object;
   }
}
  1. 修改 QuartzConfig 中的 schedulerFactoryBean 方法 ,设置 jobFactory
@Bean
public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBean,MyAdaptableJobFactory myAdaptableJobFactory){
   SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
   schedulerFactoryBean.setTriggers(cronTriggerFactoryBean.getObject());
  // 设置 setJobFactory
   schedulerFactoryBean.setJobFactory(myAdaptableJobFactory);
   return schedulerFactoryBean;
}

3.3.2 方式二——使用内部类继承

@Configuration
public class QuartzConfig {

   @Autowired
   SpringbootQuartzTask springbootQuartzTask;

   // 1 创建 job 对象
   @Bean
   public JobDetailFactoryBean jobDetailFactoryBean(){
      JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
      jobDetailFactoryBean.setJobClass(springbootQuartzTask.getClass());
      return jobDetailFactoryBean;
   }

   // 2 创建 trigger 对象
   @Bean
   public  CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
      CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
      cronTriggerFactoryBean.setJobDetail(jobDetailFactoryBean.getObject());
      cronTriggerFactoryBean.setCronExpression("*/2 * * * * ?");
      return cronTriggerFactoryBean;
   }
   // 3 创建 scheduler 对象


   @Bean
   public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBean, MyAdaptableJobFactory myAdaptableJobFactory){
      SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
      schedulerFactoryBean.setTriggers(cronTriggerFactoryBean.getObject());
//    // 设置 setJobFactory
      schedulerFactoryBean.setJobFactory(myAdaptableJobFactory);
      return schedulerFactoryBean;
   }

   @Component
    private class MyAdaptableJobFactory extends AdaptableJobFactory {

      @Autowired
      private AutowireCapableBeanFactory autowireCapableBeanFactory;

      @Override
      protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
         Object object = super.createJobInstance(bundle);
         autowireCapableBeanFactory.autowireBean(object);
         return object;
      }
   }
}

你可能感兴趣的:(springboot,spring)