1、普通关闭:
eg1.正常情况下,只要注释掉@EnableScheduling注解即可,原理就是:
- 注释掉@EnableScheduling就不会@Import(SchedulingConfiguration.class)
- 就不会注入ScheduledAnnotationBeanPostProcessor这个后置处理器
- 这个后置处理器就是用来注册执行@Scheduled定时任务的
eg2.注释掉@EnableScheduling无效,还会执行@Scheduled定时任务?
- 检查是否项目除启动类还有其它配置类用了@EnableScheduling注解
- 检查有没有引入spring-session-data-redis依赖,RedisHttpSessionConfiguration内部bean使用了@EnableScheduling
- 据说spring-boot-starter-actuator依赖也会有,但是我没找到
2、移除定时(推荐)
- 在容器启动后,获取收集的的定时任务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区别
3、开关控制
配置文件中配置一个 boolean 属性,如果是 true 的话,就开启定时任务,否则不开启。
#application.yml中的配置
scheduled:
enable: true
其实 @Scheduled 注解,是被一个叫做 ScheduledAnnotationBeanPostProcessor 的类所拦截的,所以我们可以根据配置,决定是否创建这个 bean,如果没有这个 bean,@Scheduled 就不会被拦截,那么定时任务肯定不会执行了,有了这个思路,实现起来就很简单了。需要注意的是:这种方式,启动类上面的 @EnableScheduling 需要去掉。
然后创建一个 ScheduledCondtion 类,内容如下:
public class ScheduledCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//读取配置中的属性
return Boolean.valueOf(context.getEnvironment().getProperty("scheduled.enable"));
}
}
这个类的功能很简单,就是去读取配置,然后返回一个 boolean 值。
然后创建一个配置类 ScheduledConfig ,内容如下:
@Configuration
public class ScheduledConfig {
@Conditional(ScheduledCondition.class)
@Bean
public ScheduledAnnotationBeanPostProcessor processor() {
return new ScheduledAnnotationBeanPostProcessor();
}
}
这个配置就是以 ScheduledCondtion 为条件,决定是否创建 bean。然后,启动项目,定时任务就会执行,如果我们将配置修改为 false,则不会执行。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。