您现在的位置是:首页 >技术杂谈 >关于用quartz手动创建job时,如何将job交给spring管理网站首页技术杂谈
关于用quartz手动创建job时,如何将job交给spring管理
简介关于用quartz手动创建job时,如何将job交给spring管理
文章目录
一、前言
最近盘点一些老项目,在没有用一些分布式任务框架前,一般用quartz来实现定时任务,如果想让定时任务corn表达式可修改,那么必定会动态的从数据库中读取corn表达式,并动态修改。
1、通过quartz手动创建一个任务
@Slf4j
@Component
public class SchedulerMain {
private Scheduler scheduler;
public void init() throws SchedulerException {
scheduler = StdSchedulerFactory.getDefaultScheduler();
}
//设置开始运行方法
@PostConstruct
public void start() {
//初始化Scheduler
init();
//创建一个任务,指定任务类是MainJob
JobDetail jobDetail = new JobDetail("MainJob", "main", MainJob.class);
Trigger trigger = new CronTrigger(jobDetail.getFullName() + "-Trigger", "main", "0 0 0 * * ?");
jobDetail.getJobDataMap().put("schedulerService", schedulerService);
scheduler.scheduleJob(jobDetail, trigger);
scheduler.start();
}
// 关闭定时任务
@PreDestroy
public void shutdown() {
try {
if (scheduler != null) {
scheduler.shutdown();
}
} catch (Exception e) {
}
}
}
一般手动创建一个任务就是上面过程。
看下Main的具体实现:
@Slf4j
public class MainJob implements StatefulJob {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
try {
SchedulerService schedulerService = (SchedulerService) jobExecutionContext.getJobDetail().getJobDataMap().get("schedulerService");
schedulerService.execute(false);
} catch (Exception e) {
}
}
}
2、发现问题
看到上面我们创建的MainJob 没,这个对象没有交给spring管理,如果要往这个对象中注入对象,只能在创建这个Job的时候 通过jobDataMap
放入。
在SchedulerMain
对象中,这个对象是spring管理的,所以可以通过autoWrie注入属性,而job注入属性通过jobDataMap
jobDetail.getJobDataMap().put("schedulerService", schedulerService);
在使用的时候,再从jobDataMap中获取,然后调用相应的方法。这个是不是很麻烦
3、如何将我们创建的Job交给spring创建
Quartz提供了JobFactory接口,让我们可以自定义实现创建Job的逻辑。
public interface JobFactory {
Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) throws SchedulerException;
}
这里我们用org.springframework.scheduling.quartz.SchedulerFactoryBean
注意SchedulerFactoryBean实现了FactoryBean,所以注入它时,返回是getObject方法返回的对象
@Override
public Scheduler getObject() {
//返回scheduler,scheduler是在afterPropertiesSet方法中实例化的
return this.scheduler;
}
@Override
public void afterPropertiesSet() throws Exception {
try {
this.scheduler = createScheduler(schedulerFactory, this.schedulerName);
//注意这一行代码,初始化AdaptableJobFactory
this.jobFactory = new AdaptableJobFactory();
}
}
如果我们不指定jobFactory,那么Spring就使用AdaptableJobFactory
public class AdaptableJobFactory implements JobFactory {
@Override
public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler) 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 {
//这里直接通过创建的对象,属性没有注入
return bundle.getJobDetail().getJobClass().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.");
}
}
}
3.1、再创建一个类重写AdaptableJobFactory的newJob方法,实现Job中属性自动注入
也可直接继承SpringBeanJobFactory 这个类是AdaptableJobFactory子类,重写createJobInstance方法
@Component
public class QuartzJobFactory extends SpringBeanJobFactory {
@Autowired
private AutowireCapableBeanFactory beanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object jobInstance = super.createJobInstance(bundle);
//主动注入属性
beanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
3.2、注入scheduler并将QuartzJobFactory 注入到Scheduler 中
/**
* 注入scheduler到spring,schedulerFactory这个对象返回getObject方法创建的对象
*/
<bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobFactory" ref="jobInstance"/>
<property name="quartzProperties">
<props>
<prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
<prop key="org.quartz.threadPool.threadCount">10</prop>
<prop key="org.quartz.jobStore.misfireThreshold">6000</prop>
</props>
</property>
</bean>
4、自去注入Scheduler 创建任务
@Component
public class QuartzManager {
@Autowired
private Scheduler schedulerFactory;
public void saveJobToSchedule(JobObj obj) throws SchedulerException {
//任务体
JobDetail jobDetail = JobBuilder.newJob(obj.getJobObject())
.withIdentity(obj.getJobName(),obj.getJobGroup()).build();
// 触发器
TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
triggerBuilder.withIdentity(obj.getTriggerName(), obj.getTriggerGroup());
triggerBuilder.startNow();
triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(obj.getCornTime()));
CronTrigger trigger = (CronTrigger) triggerBuilder.build();
//加入计划
schedulerFactory.scheduleJob(jobDetail, trigger);
}
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。