工作中经常遇到quartz的job注入的spring对象为null,原因是这样的:quartz每次执行一次job会将执行完成后的job销毁,下次执行的时候,重新new,这就导致job中的@Autowired注入的Spring对象为null,下面为了避免这个问题,以后的job都是从spring中获取。之前的文章只适合单个的job,这次采用Factory的方式,支持多个job。
上代码:
1、创建一个SchedulerListener类,并实现ApplicationListener,并编写自己的schedulerFactoryBean
@Configuration
public class MySchedulerListener implements ApplicationListener {
@Autowired
MyScheduler myScheduler;
@Autowired
MyJobFactory myJobFactory;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
try {
myScheduler.schedulerJob();
System.out.println("SynchronizedData job start...");
} catch (SchedulerException e) {
e.printStackTrace();
}
}
@Bean(name ="mySchedulerFactoryBean")
public SchedulerFactoryBean mySchedulerFactory() {
SchedulerFactoryBean bean = new SchedulerFactoryBean();
bean.setOverwriteExistingJobs(true);
bean.setStartupDelay(1);
bean.setJobFactory(myJobFactory);
return bean;
}
}
2、重新AdaptableJobFactory工厂,从spring获得bean(这个是很重要的)
@Component
public class MyJobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
// 调用父类的方法
Object jobInstance = super.createJobInstance(bundle);
// 进行注入
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
3、编写job
job1
public class MySchedulerJob implements Job {
private SimpleDateFormat dateFormat() {
return new SimpleDateFormat("HH:mm:ss");
}
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("AAAA: The time is now " + dateFormat().format(new Date()));
}
}
job2
public class MySchedulerJob2 implements Job {
@Autowired
NoticeTemplateService noticeTemplateService;//这个service为spring管理的对象,service可自由编写
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
List
4、编写Scheduler,并添加job
@Component
public class MyScheduler {
public void schedulerJob() throws SchedulerException {
ApplicationContext annotationContext = SpringUtil.getApplicationContext();
StdScheduler stdScheduler = (StdScheduler) annotationContext.getBean("mySchedulerFactoryBean");//获得上面创建的bean
Scheduler myScheduler =stdScheduler;
startScheduler1(myScheduler);
startScheduler2(myScheduler);
myScheduler.start();
}
public void startScheduler1(Scheduler scheduler) throws SchedulerException {
JobDetail jobDetail = JobBuilder.newJob(MySchedulerJob.class).withIdentity("job1", "jobGroup1").build();
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ?");
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1")
.withSchedule(cronScheduleBuilder).build();
scheduler.scheduleJob(jobDetail, trigger);
}
public void startScheduler2(Scheduler scheduler) throws SchedulerException {
JobDetail jobDetail = JobBuilder.newJob(MySchedulerJob2.class).withIdentity("job2", "jobGroup2").build();
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/10 * * * * ?");
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger2", "triggerGroup2")
.withSchedule(cronScheduleBuilder).build();
scheduler.scheduleJob(jobDetail, trigger);
}
}
5、SpringUtil获得application
@Component
public class SpringUtil implements ApplicationContextAware {
private static final Logger logger = LoggerFactory.getLogger(SpringUtil.class);
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
logger.info("========ApplicationContext配置成功,在普通类可以通过调用SpringUtils.getApplicationContext()获取applicationContext对象,applicationContext="
+ SpringUtil.applicationContext + "========");
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
// 通过name获取 Bean.
@SuppressWarnings("unchecked")
public static T getBean(String name) {
return (T) getApplicationContext().getBean(name);
}
// 通过class获取Bean.
public static T getBean(Class clazz) {
return getApplicationContext().getBean(clazz);
}
// 通过name,以及Clazz返回指定的Bean
public static T getBean(String name, Class clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
运行即可。