目录
一、可能的场景
在做业务平台的时候我们经常会遇到,某些跟时间打交道的需要修改状态,比如说在时间区间之前,属于未生效状态,区间之内属于有效期,区间之后,属于过期,或者需要每天 每周 每月,甚至是年为单位的做一些固定的操作。通过定时任务可以通过开启定时任务来完成这些需求。
我做合同管理模块,合同有未生效,已生效,已过期,三个状态,不可能每次用户登录的时候去判断这个状态,然后修改,这样做会在登录的逻辑里边耦合了合同业务逻辑,同时消耗了登录时间,不太可取。
还有一些需要报表统计类的批量处理任务,任务量大,类别也很多,就可以使用这个处理。当然也可以使用中间件来处理(elastic-job、xxl-job),不过本文的主题不是这个,而是spring中的实现SchedulingConfigurer。
二、基本原理
需要联合使用@EnableScheduling
与org.springframework.scheduling.annotation.SchedulingConfigurer
完成调度配置,在SchedulingConfigurer
接口中,需要实现一个void configureTasks(ScheduledTaskRegistrar taskRegistrar)
方法ScheduledTaskRegistrar
,我们发现该对象初始化完成后会执行scheduleTasks()
方法,在该方法中添加任务调度信息,最终所有的任务信息都存放在名为scheduledFutures
的集合中,通过Jdk的Executors.newSingleThreadScheduledExecutor()和配置的时间规则进行任务的调度执行。
我的Github地址: https://github.com/cheriduk/spring-boot-integration-template
首先全局看一下:
三、源码实现细节
从开启注解@EnableScheduling开始
自己觉得还是图解源码好的,截图如下:
数据流转图:
四、核心类回顾
ScheduledAnnotationBeanPostProcessor
Scheduled注解后处理器,项目启动时会扫描所有标记了
@Scheduled
注解的方法,封装成ScheduledTask
注册起来。这个处理器是处理定时任务的核心类
// 首先:非常震撼的是,它实现的接口非常的多。还好的是,大部分接口我们都很熟悉了。
// MergedBeanDefinitionPostProcessor:它是个BeanPostProcessor
// DestructionAwareBeanPostProcessor:在销毁此Bean的时候,会调用对应方法
// SmartInitializingSingleton:它会在所有的单例Bean都完成了初始化后,调用这个接口的方法
// EmbeddedValueResolverAware, BeanNameAware, BeanFactoryAware, ApplicationContextAware:都是些感知接口
// DisposableBean:该Bean销毁的时候会调用
// ApplicationListener<ContextRefreshedEvent>:监听容器的`ContextRefreshedEvent`事件
// ScheduledTaskHolder:维护本地的ScheduledTask实例
public class ScheduledAnnotationBeanPostProcessor
implements ScheduledTaskHolder, MergedBeanDefinitionPostProcessor, DestructionAwareBeanPostProcessor,
Ordered, EmbeddedValueResolverAware,