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

2023-08-06 0 2,915

目录

1.ScheduledAnnotationBeanPostProcessor

@EnableScheduling

  • @Import(SchedulingConfiguration.class)
  • 注册了ScheduledAnnotationBeanPostProcessor

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

@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

  • 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掉。

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

RefreshScope#refreshAll

  • GenericScope.BeanLifecycleWrapper#destroy
  • DisposableBeanAdapter#run
  • ScheduledAnnotationBeanPostProcessor#postProcessBeforeDestruction会将TestController里面的任务全部cancel掉。

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();
            }
        }
    }

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

取消核心流程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

  • 构造bean:nacosWatch:NacosWatch时会创建一个
  • 构造bean:taskScheduler:ThreadPoolTaskScheduler

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

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>

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

  • 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的资料请关注其它相关文章!

资源下载此资源下载价格为1小猪币,终身VIP免费,请先
由于本站资源来源于互联网,以研究交流为目的,所有仅供大家参考、学习,不存在任何商业目的与商业用途,如资源存在BUG以及其他任何问题,请自行解决,本站不提供技术服务! 由于资源为虚拟可复制性,下载后不予退积分和退款,谢谢您的支持!如遇到失效或错误的下载链接请联系客服QQ:442469558

:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可, 转载请附上原文出处链接。
1、本站提供的源码不保证资源的完整性以及安全性,不附带任何技术服务!
2、本站提供的模板、软件工具等其他资源,均不包含技术服务,请大家谅解!
3、本站提供的资源仅供下载者参考学习,请勿用于任何商业用途,请24小时内删除!
4、如需商用,请购买正版,由于未及时购买正版发生的侵权行为,与本站无关。
5、本站部分资源存放于百度网盘或其他网盘中,请提前注册好百度网盘账号,下载安装百度网盘客户端或其他网盘客户端进行下载;
6、本站部分资源文件是经压缩后的,请下载后安装解压软件,推荐使用WinRAR和7-Zip解压软件。
7、如果本站提供的资源侵犯到了您的权益,请邮件联系: 442469558@qq.com 进行处理!

猪小侠源码-最新源码下载平台 Java教程 @Scheduled定时器原理及@RefreshScope相互影响 http://www.20zxx.cn/806419/xuexijiaocheng/javajc.html

猪小侠源码,优质资源分享网

常见问题
  • 本站所有资源版权均属于原作者所有,均只能用于参考学习,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,建议提前注册好百度网盘账号,使用百度网盘客户端下载
查看详情

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务