概述
容器启动
因为任务没有定义在 ApplicationContext.xml中,而是放到了数据库中,SpringBoot启动时,怎么读取任务信息?
或者,怎么在 Spring启动完成的时候做一些事情?
创建一个类,实现 CommandLineRunner接口,实现 run方法。
从表中查出状态是 1的任务,然后构建。
Service类注入到 Job中
Spring Bean如何注入到实现了Job接口的类中?
例如在 TestTask3中,需要注入 ISysJobService,查询数据库发送邮件。
如果没有任何配置,注入会报空指针异常。
原因:
因为定时任务 Job对象的实例化过程是在 Quartz中进行的,而 Service Bean是由Spring容器管理的,Quartz察觉不到
Service Bean的存在,所以无法将 Service Bean装配到 Job对象中。
分析:
Quartz集成到 Spring中,用到 SchedulerFactoryBean,其实现了 InitializingBean方法,在唯一的方法
afterPropertiesSet()在 Bean的属性初始化后调用。
调度器用 AdaptableJobFactory对 Job对象进行实例化。所以,如果我们可以把这个 JobFactory指定为我们自定义的工厂的话,就可以在
Job实例化完成之后,把 Job纳入到 Spring容器中管理。
解决这个问题的步骤:
1、定义一个 AdaptableJobFactory,实现 JobFactory接口,实现接口定义的newJob方法,在这里面返回 Job实例
2、定义一个 MyJobFactory,继承 AdaptableJobFactory。使用 Spring的 AutowireCapableBeanFactory,把 Job实例注入到容器中。
/**
*
* 将Spring的对象注入到Quartz Job 2
*/
@Component
public class MyJobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
//调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
指定 Scheduler的 JobFactory为自定义的 JobFactory。
/**
* 这个类用于启动SpringBoot时,加载作业。run方法会自动执行。
*
* 另外可以使用 ApplicationRunner
*
*/
@Component
public class InitStartSchedule implements CommandLineRunner {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private ISysJobService sysJobService;
@Autowired
private MyJobFactory myJobFactory;
@Override
public void run(String... args) throws Exception {
/**
* 用于程序启动时加载定时任务,并执行已启动的定时任务(只会执行一次,在程序启动完执行)
*/
//查询job状态为启用的
HashMap<String,String> map = new HashMap<String,String>();
map.put("jobStatus", "1");
List<SysJob> jobList= sysJobService.querySysJobList(map);
if( null == jobList || jobList.size() ==0){
logger.info("系统启动,没有需要执行的任务... ...");
}
// 通过SchedulerFactory获取一个调度器实例
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = sf.getScheduler();
// 如果不设置JobFactory,Service注入到Job会报空指针
scheduler.setJobFactory(myJobFactory);
// 启动调度器
scheduler.start();
for (SysJob sysJob:jobList) {
String jobClassName=sysJob.getJobName();
String jobGroupName=sysJob.getJobGroup();
//构建job信息
JobDetail jobDetail = JobBuilder.newJob(getClass(sysJob.getJobClassPath()).getClass()).withIdentity(jobClassName, jobGroupName).build();
if (StringUtils.isNotEmpty(sysJob.getJobDataMap())) {
JSONObject jb = JSONObject.parseObject(sysJob.getJobDataMap());
Map<String, Object> dataMap = (Map<String, Object>)jb.get("data");
for (Map.Entry<String, Object> m:dataMap.entrySet()) {
jobDetail.getJobDataMap().put(m.getKey(),m.getValue());
}
}
//表达式调度构建器(即任务执行的时间)
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(sysJob.getJobCron());
//按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName, jobGroupName)
.withSchedule(scheduleBuilder).startNow().build();
// 任务不存在的时候才添加
if( !scheduler.checkExists(jobDetail.getKey()) ){
try {
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
logger.info("n创建定时任务失败"+e);
throw new Exception("创建定时任务失败");
}
}
}
}
public static BaseJob getClass(String classname) throws Exception
{
Class<?>
c= Class.forName(classname);
return (BaseJob)c.newInstance();
}
}
scheduler.setJobFactory(myJobFactory);
考虑这么一种情况:
正在运行的 Quartz节点挂了,而所有人完全不知情……
最后
以上就是儒雅煎蛋为你收集整理的quartz工程容器启动与 Service注入的全部内容,希望文章能够帮你解决quartz工程容器启动与 Service注入所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复