springboot 整合 quartz 配置定时任务
1 quartz 的基本使用
1.1 引入依赖
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</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-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</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 方式一——普通的继承方式
- 重写 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;
}
}
- 修改 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;
}
}
}