java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Scheduled定时器RefreshScope

@Scheduled定时器原理及@RefreshScope相互影响

作者:王侦

这篇文章主要为大家介绍了@Scheduled定时器原理及@RefreshScope相互影响详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

1.ScheduledAnnotationBeanPostProcessor

@EnableScheduling

@RestController
@RefreshScope  //动态感知修改后的值
public class TestController implements ApplicationListener<RefreshScopeRefreshedEvent>{
    @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

1.2 RefreshScope处理ContextRefreshedEvent创建refresh中的bean

并调用ScheduledAnnotationBeanPostProcessor#postProcessAfterInitialization找出TestController中加了@Scheduled注解的方法。

ScheduledAnnotationBeanPostProcessor#postProcessAfterInitialization

1.3 ScheduledAnnotationBeanPostProcessor本身也能处理ContextRefreshedEvent

这里真正开始调度1.2中找到的任务。

ScheduledAnnotationBeanPostProcessor#onApplicationEvent

2.@RefreshScope的影响

当Nacos Config配置中心发布配置时,会调用RefreshScope#refreshAll。
此时会ScheduledAnnotationBeanPostProcessor#postProcessBeforeDestruction会将加了@RefreshScope的TestController里面的任务全部cancel掉。

    public void refreshAll() {
        super.destroy();
        this.context.publishEvent(new RefreshScopeRefreshedEvent());
    }

RefreshScope#refreshAll

ScheduledAnnotationBeanPostProcessor#postProcessBeforeDestruction

    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) {
        Set<ScheduledTask> tasks;
        synchronized (this.scheduledTasks) {
            tasks = this.scheduledTasks.remove(bean);
        }
        if (tasks != null) {
            for (ScheduledTask task : tasks) {
                task.cancel();
            }
        }
    }

取消核心流程GenericScope#destroy()

    public void destroy() {
        List<Throwable> errors = new ArrayList<Throwable>();
        Collection<BeanLifecycleWrapper> 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

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<TaskSchedulerCustomizer> 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<RefreshScopeRefreshedEvent>

这样做为什么能够保证定时任务正常执行?

以上就是@Scheduled定时器原理及@RefreshScope相互影响的详细内容,更多关于Scheduled定时器RefreshScope的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文