本文讨论了在SpringBoot项目中,如何避免普通注释`@EnableScheduling`失效导致的定时任务执行。作者提供了通过`ApplicationListener`监听应用启动事件并移除定时任务,以及使用`ApplicationRunner`的两种解决方案。 摘要由CSDN通过智能技术生成

正常情况下,只要注释掉@EnableScheduling注解即可,原理就是:

  • 注释掉@EnableScheduling就不会@Import(SchedulingConfiguration.class)
  • 就不会注入ScheduledAnnotationBeanPostProcessor这个后置处理器
  • 这个后置处理器就是用来注册执行@Scheduled定时任务的
2. 注释掉@EnableScheduling无效,还会执行@Scheduled定时任务

这种情况要检查是否项目除启动类还有其它配置类用了@EnableScheduling注解

  • 检查有没有引入spring-session-data-redis依赖,RedisHttpSessionConfiguration内部bean使用了@EnableScheduling
  • 据说spring-boot-starter-actuator依赖也会有,但是我没找到

这种情况如何屏蔽掉定时任务呢?如下代码:

  • 在容器启动后,获取收集的的定时任务Set<ScheduledTask>
  • 通过后置处理器的postProcessBeforeDestruction来移除任务,这样就不会执行了
@Component public class ApplicationListenerImpl implements ApplicationListener < ApplicationReadyEvent > { @Autowired private ScheduledAnnotationBeanPostProcessor beanPostProcessor ; @Override public void onApplicationEvent ( ApplicationReadyEvent event ) { // 拿到所有的task(带包装) Set < ScheduledTask > tasks = beanPostProcessor . getScheduledTasks ( ) ; Set < Object > rawTasks = new HashSet < > ( tasks . size ( ) ) ; for ( ScheduledTask task : tasks ) { Task t = task . getTask ( ) ; Runnable runnableTemp = t . getRunnable ( ) ; ScheduledMethodRunnable runnable = null ; if ( runnableTemp instanceof ScheduledMethodRunnable ) { runnable = ( ScheduledMethodRunnable ) runnableTemp ; if ( runnable == null ) { continue ; Object taskObject = runnable . getTarget ( ) ; // 将task所关联的对象放到Set中(就是带@Scheduled方法的类) rawTasks . add ( taskObject ) ; // 调用postProcessBeforeDestruction()方法,将task移除并cancel for ( Object obj : rawTasks ) { beanPostProcessor . postProcessBeforeDestruction ( obj , "scheduledTasks" ) ; System . out . println ( "listener" ) ;

也可以通过实现ApplicationRunner的方式
`
区别在于:
ApplicationRunner、ApplicationListener区别

@ Schedule d 定时任务 可配置的表达式有 cron、zone、fixedDelay、fixedRate、initialDelay 等,当 定时任务 满足某个条件时,我们想停止它,修改代码显然是不适宜的办法,怎么办呢? 一、如果类中只有一个 定时任务 ,可以这么写 在这里插入代码片
SpringBoot 定时任务 @ Schedule d注解 Spring 中的@ Schedule d可以进行 定时任务 开发,定时执行方法。 首先要在执行类加注解@ Enabl eSch edu lin g,具体方法上加@ Schedule d import org. spring framework.sch edu lin g.annotation. Enabl eSch edu lin g; import org. spring framework.sch edu lin g.annotation. Schedule d; import org. spring fra
@Data @Component public class ThreadPool Task Schedule rComponent extends ThreadPool Task Schedule r { private Map<Object, Schedule dFuture<?>> schedule
项目中会用到@ Schedule d(cron = “0 30 0 * * ?”)作为定时器触发,cron里面的表达式是设置具体的定时触发时间,有一次在本地测试的时候,先修改了本地时间,然后再 启动 项目,定时器死活触发不了,后来经过log日志的观察发现,程序在 启动 的时候,获取的时间已经超过触发时间了,虽然更改了本地时间,也不能触发,所以得先更改时间,再 启动 程序,这样就可以避免该问题。
项目开发中经常需要执行一些 定时任务 ,比如需要在每天凌晨时候,分析一次前一天的日志信息。 Spring 为我们提供了异步执行任务调度的方式,提供 Task Executor 、 Task Schedule r 接口。 SpringBoot 中使用两个注解:@ Enabl eSch edu lin g、@ Schedule d来简单实现 定时任务 。 【1】@ Schedule d注解 按照惯例,先看源码: * ...