项目场景:
根据数据库配置的时间执行一次定时任务
问题描述:
使用SchedulingConfigurer类的configureTasks方法添加自定义执行时间的定时任务时,本来是可以在项目启动时自动执行的,但是项目启动报错
@Configuration
public class ScheduledConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
//scheduledTaskRegistrar.setScheduler(Executors.newScheduledThreadPool(5));
//可以实现动态调整定时任务的执行频率
scheduledTaskRegistrar.addTriggerTask(
//1.添加任务内容(Runnable)
() -> System.out.println("cccccccccccccccc--->" + Thread.currentThread().getId()),
//2.设置执行周期(Trigger)
triggerContext -> {
//2.1 从数据库动态获取执行周期
//String cron = "0/2 * * * * ? ";
String cron = "0 " + "10 " + "13 " + "15 " + "2 ?";
//2.2 合法性校验.
// if (StringUtils.isEmpty(cron)) {
// // Omitted Code ..
// }
//2.3 返回执行周期(Date)
return new CronTrigger(cron).nextExecutionTime(triggerContext);
}
);
}
}
原因分析:
由于在项目中自动注入了ThreadPoolTaskScheduler这个bean,根据TaskSchedulingAutoConfiguration的自动配置代码如下:
@Bean @ConditionalOnBean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME) @ConditionalOnMissingBean({ SchedulingConfigurer.class, TaskScheduler.class, ScheduledExecutorService.class }) public ThreadPoolTaskScheduler taskScheduler(TaskSchedulerBuilder builder) { return builder.build(); }
可以看出ThreadPoolTaskScheduler这个bean成为bean的前提是SchedulingConfigurer这个bean在容器中不存在,而项目中刚好使用了SchedulingConfigurer这个bean,所以导致ThreadPoolTaskScheduler这个bean无法引入
解决方案:
调整方案,直接使用ThreadPoolTaskScheduler这个bean进行自定义执行时间,来执行定时任务,代码如下:
@Autowired
private ThreadPoolTaskScheduler taskScheduler;
public void sendMsg() {
taskScheduler.schedule(
//1.添加任务内容(Runnable)
() -> System.out.println("cccccccccccccccc--->" +
Thread.currentThread().getId()),
//2.设置执行周期(Trigger)
triggerContext -> {
//2.1 从数据库动态获取执行周期
//String cron = "0/2 * * * * ? ";
String cron = "0 " + "07 " + "14 " + "15 " + "2 ?";
//2.2 合法性校验.
// if (StringUtils.isEmpty(cron)) {
// // Omitted Code ..
// }
//2.3 返回执行周期(Date)
return new CronTrigger(cron).nextExecutionTime(triggerContext);
}
);
}
上面的方法,需要手动显示调用才能执行,但是同样能达到动态定时执行