Spring Boot 定时任务四 :SpringBoot整合Quartz
通过上一篇,我们知道quartz的使用只需要3步,而springboot整合Quartz其实就是实现此3个步骤。
一、pom文件新增jar
<!-- Sprng tx 坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
二、定时任务
沿用上一篇的任务文件MyJob.java
三、创建Quartz的配置文件
此文件其实就是实现Quartzding定时任务的三个步骤。
@Configuration
public class QuartzConfig {
/**
* 1.创建Job 对象
*/
@Bean
public JobDetailFactoryBean jobDetailFactoryBean(){
JobDetailFactoryBean factory = new JobDetailFactoryBean();
//关联我们自己的Job 类
factory.setJobClass(MyJob.class);
return factory;
}
/**
* 2.创建Trigger 对象
*/
@Bean
public CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
CronTriggerFactoryBean factory = new CronTriggerFactoryBean();
factory.setJobDetail(jobDetailFactoryBean.getObject());
//设置触发时间
factory.setCronExpression("0/2 * * * * ?");
return factory;
}
/**
* 3.创建Scheduler 对象
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean triggerFactoryBean){
SchedulerFactoryBean factory = new SchedulerFactoryBean();
//关联trigger
factory.setTriggers(triggerFactoryBean.getObject());
return factory;
}
}
四、运行结果
执行Springboot的启动文件,控制台的运行结果如下,可以看出每隔2秒执行一次任务
五、模拟服务层 UserService
在现实场景下,定时任务中肯定是需要调用服务层的功能,那么就要将服务层注入到任务中。
这里做个简单的模拟,新增一个用户功能
@Service
public class UserService {
public void addUser() {
System.out.println("**>addUser");
}
}
六、注入service
在定时任务zh中注入service
@Autowired
UserService userService;
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
this.userService.addUser();
System.out.println("任务-->"+new Date());
}
运行后,控制台报错如下
这是应该注入进来的userService并没有实例化,而我们的MyJob的实例化是通过Job对象中的JobDetailFactoryBean来实例化的,参见代码 JobDetailFactoryBean factory = new JobDetailFactoryBean();
//关联我们自己的Job 类
factory.setJobClass(MyJob.class);
而我们的定时任务的实例化是通过AdaptableJobFactory类中的createJobInstance方法实现,源码如下
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Class<?> jobClass = bundle.getJobDetail().getJobClass();
return ReflectionUtils.accessibleConstructor(jobClass).newInstance();
}
从源码可以看出,我们的类是被AdaptableJobFactory通过反射的方式来实例化,并没有被Spring实例化。那么我们只要在执行任务调度之前,将相应的对象注入到Spring MVC中即可。
七、自定义AdaptableJobFactory
重写反射的方法createJobInstance
@Component
public class MyAdaptableJobFactory extends AdaptableJobFactory {
// 可以将一个对象添加到SpringIOC 容器中,并且完成该对象注入
@Autowired
private AutowireCapableBeanFactory autowireCapableBeanFactory;
/**
* 该方法需要将实例化的任务对象手动的添加到springIOC 容器中并且完成对象的注入
*/
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object obj = super.createJobInstance(bundle);
//将obj 对象添加Spring IOC 容器中,并完成注入
this.autowireCapableBeanFactory.autowireBean(obj);
return obj;
}
}
八、修改Scheduler
/**
* 3.创建Scheduler 对象
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean triggerFactoryBean,MyAdaptableJobFactory jobFactory){
SchedulerFactoryBean factory = new SchedulerFactoryBean();
//关联trigger
factory.setTriggers(triggerFactoryBean.getObject());
factory.setJobFactory(jobFactory);
return factory;
}
九、运行结果