1.ScheduledAnnotationBeanPostProcessor
@EnableScheduling
- @Import(SchedulingConfiguration.class)
- 注册了ScheduledAnnotationBeanPostProcessor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @RestController @RefreshScope //动态感知修改后的值 public class TestController implements ApplicationListener{ @Value ( "${common.age}" ) String age; @Value ( "${common.name}" ) String name; @GetMapping ( "/common" ) public String hello() { return name+ "," +age; } //触发@RefreshScope执行逻辑会导致@Scheduled定时任务失效 @Scheduled (cron = "*/3 * * * * ?" ) //定时任务每隔3s执行一次 public void execute() { System.out.println( "定时任务正常执行。。。。。。" ); } @Override public void onApplicationEvent(RefreshScopeRefreshedEvent event) { this .execute(); } } |
1.1 SmartInitializingSingleton#afterSingletonsInstantiated
ScheduledAnnotationBeanPostProcessor#afterSingletonsInstantiated
- DefaultListableBeanFactory#preInstantiateSingletons
- SmartInitializingSingleton#afterSingletonsInstantiated
- 没干啥重要事情
1.2 RefreshScope处理ContextRefreshedEvent创建refresh中的bean
并调用ScheduledAnnotationBeanPostProcessor#postProcessAfterInitialization找出TestController中加了@Scheduled注解的方法。
ScheduledAnnotationBeanPostProcessor#postProcessAfterInitialization
- 发布ContextRefreshedEvent
- RefreshScope#onApplicationEvent
- Object bean = this.context.getBean(name); 获取scope为refresh的bean:scopedTarget.testController
- 会调用至postProcessAfterInitialization
- 找到有@Scheduled注解的方法execute()
- tasks.add(this.registrar.scheduleCronTask(new CronTask(runnable, new CronTrigger(cron, timeZone))));
1.3 ScheduledAnnotationBeanPostProcessor本身也能处理ContextRefreshedEvent
这里真正开始调度1.2中找到的任务。
ScheduledAnnotationBeanPostProcessor#onApplicationEvent
- ScheduledAnnotationBeanPostProcessor也会处理ContextRefreshedEvent
- ScheduledAnnotationBeanPostProcessor#finishRegistration
- this.taskScheduler设置为ThreadPoolTaskScheduler(哪里配置的?)
- ScheduledTaskRegistrar#afterPropertiesSet
- ScheduledTaskRegistrar#scheduleTasks
- 开始执行任务,这cronTasks不为空,则执行该任务
addScheduledTask(scheduleCronTask(task)); - ScheduledTaskRegistrar#scheduleCronTask
- scheduledTask.future = this.taskScheduler.schedule(task.getRunnable(), task.getTrigger());
- ThreadPoolTaskScheduler#schedule
- ReschedulingRunnable#schedule以及ReschedulingRunnable#run实现定时调度,线程池为ScheduledThreadPoolExecutor
2.@RefreshScope的影响
当Nacos Config配置中心发布配置时,会调用RefreshScope#refreshAll。
此时会ScheduledAnnotationBeanPostProcessor#postProcessBeforeDestruction会将加了@RefreshScope的TestController里面的任务全部cancel掉。
1 2 3 4 | public void refreshAll() { super .destroy(); this .context.publishEvent( new RefreshScopeRefreshedEvent()); } |
RefreshScope#refreshAll
- GenericScope.BeanLifecycleWrapper#destroy
- DisposableBeanAdapter#run
- ScheduledAnnotationBeanPostProcessor#postProcessBeforeDestruction会将TestController里面的任务全部cancel掉。
ScheduledAnnotationBeanPostProcessor#postProcessBeforeDestruction
1 2 3 4 5 6 7 8 9 10 11 12 | @Override public void postProcessBeforeDestruction(Object bean, String beanName) { Set tasks; synchronized ( this .scheduledTasks) { tasks = this .scheduledTasks.remove(bean); } if (tasks != null ) { for (ScheduledTask task : tasks) { task.cancel(); } } } |
取消核心流程GenericScope#destroy()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public void destroy() { List errors = new ArrayList(); Collection wrappers = this .cache.clear(); for (BeanLifecycleWrapper wrapper : wrappers) { try { Lock lock = this .locks.get(wrapper.getName()).writeLock(); lock.lock(); try { wrapper.destroy(); } finally { lock.unlock(); } } catch (RuntimeException e) { errors.add(e); } } if (!errors.isEmpty()) { throw wrapIfNecessary(errors.get( 0 )); } this .errors.clear(); } |
2.1 ThreadPoolTaskScheduler在哪里配置的?
ThreadPoolTaskScheduler
- 构造bean:nacosWatch:NacosWatch时会创建一个
- 构造bean:taskScheduler:ThreadPoolTaskScheduler
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class TaskSchedulingAutoConfiguration { @Bean @ConditionalOnBean (name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME) @ConditionalOnMissingBean ({ SchedulingConfigurer. class , TaskScheduler. class , ScheduledExecutorService. class }) public ThreadPoolTaskScheduler taskScheduler(TaskSchedulerBuilder builder) { return builder.build(); } @Bean @ConditionalOnMissingBean public TaskSchedulerBuilder taskSchedulerBuilder(TaskSchedulingProperties properties, ObjectProvider taskSchedulerCustomizers) { TaskSchedulerBuilder builder = new TaskSchedulerBuilder(); builder = builder.poolSize(properties.getPool().getSize()); Shutdown shutdown = properties.getShutdown(); builder = builder.awaitTermination(shutdown.isAwaitTermination()); builder = builder.awaitTerminationPeriod(shutdown.getAwaitTerminationPeriod()); builder = builder.threadNamePrefix(properties.getThreadNamePrefix()); builder = builder.customizers(taskSchedulerCustomizers); return builder; } |
2.2 TestController改造成ApplicationListener
这样做为什么能够保证定时任务正常执行?
- RefreshScope#refreshAll
- 发布RefreshScopeRefreshedEvent事件
- 调用到TestController代理对象#onApplicationEvent
- CglibAopProxy.DynamicAdvisedInterceptor#intercept
- SimpleBeanTargetSource#getTarget
- AbstractBeanFactory#getBean获取scopedTarget.testController
- GenericScope#get
- 会创建真正的TestController实例,然后初始化后调用ScheduledAnnotationBeanPostProcessor#postProcessAfterInitialization找出TestController中加了@Scheduled注解的方法
- TestController#onApplicationEvent
- this.execute();
- 真正调用的是ReschedulingRunnable#run
以上就是@Scheduled定时器原理及@RefreshScope相互影响的详细内容,更多关于Scheduled定时器RefreshScope的资料请关注IT俱乐部其它相关文章!