一. Spring任务调度介绍
介绍下Spring的任务调度,启动一个间隔1秒的定时任务,首先开启Spring定时任务:
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
@Configuration
@EnableScheduling
public class TimerConfig {
}
在@Configuration注解下添加@EnableScheduling就可以启动任务调度
然后配置定时任务:
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class TimerTask {
@Scheduled(fixedDelay = 2000)
public void doTask() {
System.out.println("task executing");
}
}
这里设置2秒执行间隔
最后启动Spring容器:
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) throws InterruptedException {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext();
annotationConfigApplicationContext.scan("com.tubemogul.springsecuredemo.springDemo.basicTimer");
annotationConfigApplicationContext.refresh();
}
}
在控制台中可以看到定时任务被执行了:
但是现在有个新需求,要求动态启停任务,也就是在程序中启动/停止定时任务,当然比较简单的做法是在定时任务中加个bool变量,动态改变这个变量来控制是否执行这个任务,但如果定时任务很多,代码就很丑了,而且一堆空任务会无谓的消耗计算机资源。
Spring调度器本身没有实现这个功能,下面我们就在Spring调度器的基础上,实现动态启停。
二. Spring 任务调度原理分析
在实现自己定制的任务调度器以前,先分析一下Spring任务调度器的原理。
我们从第一个配置看起@EnableScheduling,这是这个注解的源码:
关键在@Import注解,这个注解导入了SchedulingConfiguration类:
这也是一个配置类,在这个类中导入了ScheduledAnnotationBeanPostProcessor进入Spring容器,从名字上就可以看出这个类是一个BeanPostprocessor,了解Spring容器原理可知,后处理器的postProcessBeforeInitialization(Object bean, String beanName)方法和postProcessAfterInitialization(Object bean, String beanName)方法在Bean创建后被调用(这两个方法调用时间有细微差别,前者在自定义初始化代码生效前调用,后者在自定义初始化代码生效后调用)
有用的逻辑在postProcessBeforeInitialization(Object bean, String beanName)方法里面: