@Scheduled和@SchedulerLock原理 - ambition0802/spring-practice GitHub Wiki
-
ScheduledAnnotationBeanPostProcessor.java 的postProcessorAfterInitialization方法中扫描bean的所有方法,查看bean方法有无@Scheduled注解。
-
@Scheduled有多种配置,initialDelay、cron、fixedDelay、fixedRate,不同的定时配置,通过org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor#registrar(ScheduledTaskRegistrar)的不同方法去注册执行。
比如fixedDelay通过registrar的scheduleFixedDelayTask方法将定时任务注册到registrar的fixedDelayTasks(List)中。
-
registrar实现了InitializingBean接口,在InitializingBean接口的afterPropertiesSet方法中(其实是被onApplication调用的,不是因为InitializingBean调用的?),遍历fixedDelayTasks中注册的fixedDelay任务,最终通过JUC包下的ScheduledThreadPoolExecutor来执行定时任务。
@SchedulerLock
-
由shedlock组件实现:
<dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-spring</artifactId> <version>2.5.0</version> </dependency> <dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-provider-jdbc-template</artifactId> <version>2.5.0</version> </dependency>
-
@SchedulerLock通过ScheduledTaskRegistrar和Spring的@Scheduled进行集成,shedlock将自己的LockableTaskScheduler注入到Spring容器中(具体过程?),ScheduledTaskRegistrar将自己的TaskScheduler设置成LockableTaskScheduler
-
在@Scheduled的第3步骤中,LockableTaskScheduler在scheduleWithFixedDelay方法中将task包装成LockableRunnable.
-
在LockableRunnable的run方法中,使用LockingTaskExecutor去真正执行任务,在执行开始的时候,判断有没有配置shedlock,如果由,就走shedlock的分布式锁的逻辑。如果没有就和正常的@Scheduled任务一样运行。
-
shedlock的分布式锁依赖于单点数据库实现,shedlock需要拿到数据库的DataSource。shedlock使用LockProvider包装DataSource,所以插件内要连接数据库,只要在插件容器中创建支持vt-web的DataSource的LockProvider Bean就可以了。
vt-web中启用@Scheduled,使用的是@EnableSchduling注解,实际上@EnableSchduling注解是通过@Import注解引入了ScheduleingConfiguration,ScheduleingConfiguration再往容器中添加ScheduledAnnotationBeanPostProcessor实例(即bean)。
@EnableSchduling需要和@Configuration配和使用。在处理被@Configuration注解的类的时候,会去找这个类上面的@Import注解,从而将@Import注解中指定的类(ScheduleingConfiguration)加载进来。ScheduleingConfiguration加载进来后通过@Bean创建ScheduledAnnotationBeanPostProcessor。