Spring Boot:在Quartz作业执行中使用@Service

在一个应用程序中,由于我将它从经典的Spring webapp(部署在系统Tomcat中)转换为Spring Boot(V1.2.1)应用程序,我面临的问题是基于Quartz的预定作业不再起作用。

我安排这些Quartz工作如下:

// My own Schedule object which holds data about what to schedule when Schedule schedule = scheduleService.get(id of the schedule); String scheduleId = schedule.getId(); JobKey jobKey = new JobKey(scheduleId); TriggerKey triggerKey = new TriggerKey(scheduleId); JobDataMap jobData = new JobDataMap(); jobData.put("scheduleId", scheduleId); JobBuilder jobBuilder = JobBuilder.newJob(ScheduledActionRunner.class) .withIdentity(jobKey) .withDescription(schedule.getName()) .usingJobData(jobData); JobDetail job = jobBuilder.build(); TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger() .forJob(jobKey) .withIdentity(triggerKey) .withDescription(schedule.getName()); triggerBuilder = triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(schedule.toCronExpression())); Trigger trigger = triggerBuilder.build(); org.quartz.Scheduler scheduler = schedulerFactoryBean.getScheduler(); scheduler.scheduleJob(job, trigger); 

ScheduledActionRunner

 @Component public class ScheduledActionRunner extends QuartzJobBean { @Autowired private ScheduleService scheduleService; public ScheduledActionRunner() { } @Override public void executeInternal(final JobExecutionContext context) throws JobExecutionException { SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); final JobDataMap jobDataMap = context.getMergedJobDataMap(); final String scheduleId = jobDataMap.getString("scheduleId"); final Schedule schedule = scheduleService.get(scheduleId); // here it goes BANG since scheduleService is null } } 

ScheduleService是一个经典的Spring服务,它从Hibernate获取数据。 正如我上面所说的,这一直很好,直到我转移到Spring Boot。

当我用经典的Spring应用程序实现这段代码时, SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); 做了诀窍来照顾自动assembly服务。

在Spring Boot环境中再次使用它需要什么?

编辑:

最后,我选择放弃使用Quartz而不是Spring的ThreadPoolTask​​Scheduler。代码非常简化,并且按预期工作。

SpringBeanAutowiringSupport使用Web应用程序上下文,在您的情况下不可用。 如果您需要石英中的弹簧管理豆,您应该使用弹簧提供的石英支撑。 这将使您可以完全访问所有托管bean。 有关详细信息,请参阅http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html上的spring docs中的quartz部分。 另请参阅以下使用Quart with spring managed beans的示例。 示例基于您的代码。 因此,您可以使用以下弹簧替代方案更改第一个代码段(完成石英初始化的位置)。

创建工作细节工厂

 @Component public class ScheduledActionRunnerJobDetailFactory extends JobDetailFactoryBean { @Autowired private ScheduleService scheduleService; @Override public void afterPropertiesSet() { setJobClass(ScheduledActionRunner.class); Map data = new HashMap(); data.put("scheduleService", scheduleService); setJobDataAsMap(data); super.afterPropertiesSet(); } } 

创建触发器工厂

 @Component public class ActionCronTriggerFactoryBean extends CronTriggerFactoryBean { @Autowired private ScheduledActionRunnerJobDetailFactory jobDetailFactory; @Value("${cron.pattern}") private String pattern; @Override public void afterPropertiesSet() throws ParseException { setCronExpression(pattern); setJobDetail(jobDetailFactory.getObject()); super.afterPropertiesSet(); } } 

最后创建SchedulerFactory

 @Component public class ActionSchedulerFactoryBean extends SchedulerFactoryBean { @Autowired private ScheduledActionRunnerJobDetailFactory jobDetailFactory; @Autowired private ActionCronTriggerFactoryBean triggerFactory; @Override public void afterPropertiesSet() throws Exception { setJobDetails(jobDetailFactory.getObject()); setTriggers(triggerFactory.getObject()); super.afterPropertiesSet(); } } 

我的回答并不完全符合您的问题,但是Spring为您提供了另一种能力 – 在任何服务上启动基于cron-expression的调度程序。

使用Spring.Boot,您可以通过简单的放置将应用程序配置为使用调度程序

 @EnableScheduling public class Application{ .... 

之后,只需在@Service public (!)方法上进行注释

 @Service public class MyService{ ... @Scheduled(cron = "0 * * * * MON-FRI") public void myScheduledMethod(){ .... }