Springboot写上注解@Scheduled就可以实现定时任务,

这里对其源码做一点分析

@Service
public class MyScheduled {@Scheduled(cron="${time.cron}")void paoapaoScheduled() {System.out.println("Execute at " + System.currentTimeMillis());}
}

配置文件100秒一次

time.cron=*/100 * * * * *

重要的类ScheduledAnnotationBeanPostProcessor

@Nullableprivate BeanFactory beanFactory;
private void finishRegistration() {if (this.scheduler != null) {this.registrar.setScheduler(this.scheduler);}if (this.beanFactory instanceof ListableBeanFactory) {Map<String, SchedulingConfigurer> beans =((ListableBeanFactory) this.beanFactory).getBeansOfType(SchedulingConfigurer.class);List<SchedulingConfigurer> configurers = new ArrayList<>(beans.values());AnnotationAwareOrderComparator.sort(configurers);for (SchedulingConfigurer configurer : configurers) {configurer.configureTasks(this.registrar);}}if (this.registrar.hasTasks() && this.registrar.getScheduler() == null) {Assert.state(this.beanFactory != null, "BeanFactory must be set to find scheduler by type");try {// Search for TaskScheduler bean...this.registrar.setTaskScheduler(resolveSchedulerBean(this.beanFactory, TaskScheduler.class, false));}catch (NoUniqueBeanDefinitionException ex) {logger.trace("Could not find unique TaskScheduler bean", ex);try {this.registrar.setTaskScheduler(resolveSchedulerBean(this.beanFactory, TaskScheduler.class, true));}catch (NoSuchBeanDefinitionException ex2) {if (logger.isInfoEnabled()) {logger.info("More than one TaskScheduler bean exists within the context, and " +"none is named 'taskScheduler'. Mark one of them as primary or name it 'taskScheduler' " +"(possibly as an alias); or implement the SchedulingConfigurer interface and call " +"ScheduledTaskRegistrar#setScheduler explicitly within the configureTasks() callback: " +ex.getBeanNamesFound());}}}catch (NoSuchBeanDefinitionException ex) {logger.trace("Could not find default TaskScheduler bean", ex);// Search for ScheduledExecutorService bean next...try {this.registrar.setScheduler(resolveSchedulerBean(this.beanFactory, ScheduledExecutorService.class, false));}catch (NoUniqueBeanDefinitionException ex2) {logger.trace("Could not find unique ScheduledExecutorService bean", ex2);try {this.registrar.setScheduler(resolveSchedulerBean(this.beanFactory, ScheduledExecutorService.class, true));}catch (NoSuchBeanDefinitionException ex3) {if (logger.isInfoEnabled()) {logger.info("More than one ScheduledExecutorService bean exists within the context, and " +"none is named 'taskScheduler'. Mark one of them as primary or name it 'taskScheduler' " +"(possibly as an alias); or implement the SchedulingConfigurer interface and call " +"ScheduledTaskRegistrar#setScheduler explicitly within the configureTasks() callback: " +ex2.getBeanNamesFound());}}}catch (NoSuchBeanDefinitionException ex2) {logger.trace("Could not find default ScheduledExecutorService bean", ex2);// Giving up -> falling back to default scheduler within the registrar...logger.info("No TaskScheduler/ScheduledExecutorService bean found for scheduled processing");}}}this.registrar.afterPropertiesSet();}

bean

找到自定义的MyScheduled

这里先逆向找到可见代码,再往上找到他的赋值地方

if (this.registrar.hasTasks() && this.registrar.getScheduler() == null) {Assert.state(this.beanFactory != null, "BeanFactory must be set to find scheduler by type");try {// Search for TaskScheduler bean...this.registrar.setTaskScheduler(resolveSchedulerBean(this.beanFactory, TaskScheduler.class, false));}catch (NoUniqueBeanDefinitionException ex) {logger.trace("Could not find unique TaskScheduler bean", ex);try {this.registrar.setTaskScheduler(resolveSchedulerBean(this.beanFactory, TaskScheduler.class, true));}

重要类ScheduledThreadPoolExecutor

参考:https://www.jianshu.com/p/502f9952c09b

ScheduledThreadPoolExecutor继承了ThreadPoolExecutor,也就是说ScheduledThreadPoolExecutor拥有execute()和submit()提交异步任务的基础功能,ScheduledThreadPoolExecutor类实现了ScheduledExecutorService,该接口定义了ScheduledThreadPoolExecutor能够延时执行任务和周期执行任务的功能。

ScheduledThreadPoolExecutor也两个重要的内部类:DelayedWorkQueueScheduledFutureTask。可以看出DelayedWorkQueue实现了BlockingQueue接口,也就是一个阻塞队列,ScheduledFutureTask则是继承了FutureTask类,也表示该类用于返回异步任务的结果。

/*** @throws RejectedExecutionException {@inheritDoc}* @throws NullPointerException       {@inheritDoc}*/public ScheduledFuture<?> schedule(Runnable command,long delay,TimeUnit unit) {if (command == null || unit == null)throw new NullPointerException();RunnableScheduledFuture<?> t = decorateTask(command,new ScheduledFutureTask<Void>(command, null,triggerTime(delay, unit)));delayedExecute(t);return t;}

到了schedule这里:

增加定时任务ScheduledTaskRegistrar

protected void scheduleTasks() {if (this.taskScheduler == null) {this.localExecutor = Executors.newSingleThreadScheduledExecutor();this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);}if (this.triggerTasks != null) {for (TriggerTask task : this.triggerTasks) {addScheduledTask(scheduleTriggerTask(task));}}if (this.cronTasks != null) {for (CronTask task : this.cronTasks) {addScheduledTask(scheduleCronTask(task));}}if (this.fixedRateTasks != null) {for (IntervalTask task : this.fixedRateTasks) {addScheduledTask(scheduleFixedRateTask(task));}}if (this.fixedDelayTasks != null) {for (IntervalTask task : this.fixedDelayTasks) {addScheduledTask(scheduleFixedDelayTask(task));}}}

遍历arrayList

跳出refresh

Spring如何添加钩子函数

这里没有注册钩子函数自然是null

进Runtime.getRuntime().addShutdownHook(this.shutdownHook);

终于完了

============================

触发定时

倒着看就知道怎么调用的,实际上是反射执行上述方法的

invoke方法用来在运行时动态地调用某个实例的方法

这里实行了Runnable 接口:

反射,线程,线程池 底层还是这些技术!需要好好研究这块代码,加深理解基本原理。

扩展信息:SpringBoot中定时任务默认是串行执行 如何设置并行

SpringBoot 使用@Scheduled注解配置串行、并行定时任务

Spring Boot 中实现定时任务的两种方式

SpringBoot源码分析之@Scheduled相关推荐

  1. SpringBoot源码分析(二)之自动装配demo

    SpringBoot源码分析(二)之自动装配demo 文章目录 SpringBoot源码分析(二)之自动装配demo 前言 一.创建RedissonTemplate的Maven服务 二.创建测试服务 ...

  2. Springboot源码分析第一弹 - 自动装配实现

    Springboot就不用多了吧,解放Java开发双手的神器. 最显著的特点就是,去配置化,自动装配,自动配置.让开发人员只需要注重业务的开发 今天就来了解一下自动装配的源码是怎么实现的 预先准备 直 ...

  3. SpringBoot源码分析之内置Servlet容器

    原文链接:http://fangjian0423.github.io/2017/05/22/springboot-embedded-servlet-container/ SpringBoot内置了Se ...

  4. springboot源码分析

    快速开发底层原理 SpringBoot核心理念 能够实现帮助开发者快速的整合第三方框架(Spring.Mybatis.hibernate) 原理:Maven依赖封装整合和自定义starter. 完全去 ...

  5. Springboot源码分析之内嵌tomcat源码分析

    Springboot源码是内嵌tomcat的,这个和完整的tomcat还是不同. 内嵌tomcat的源码在tomcat-embed-core等3个jar包里 展开tomcat-embed-core的c ...

  6. springboot源码分析之环境属性构造过程1

    使用springboot的目的就是在项目开发中,快速出东西,因此springboot对于配置文件的格式支持是非常丰富的,最常见的配置文件后缀有如下四种:properties.xml.yml.yaml, ...

  7. springboot源码分析 - AbstractRoutingDataSource多数据源方案的分析

    2019独角兽企业重金招聘Python工程师标准>>> 原本想用springboot+mybatis做多数据源的切换方案,想通过借鉴网上现有的方案,结果搜索后大量都是使用Abstra ...

  8. Springboot 源码分析 —— @Endpoint 注解生效原理解析

    文章目录 1 WebMvcEndpointManagementContextConfiguration 1.1 webEndpointServletHandlerMapping 1.2 Control ...

  9. 深入浅出SpringBoot源码分析

    Spring源码非常多,不要迷失在源码的汪洋大海里,抓住主要脉络,有需要再研究即可. Bean的初始化 1.发现所有的bean ComponentScanAnnotationParser.parse( ...

最新文章

  1. leetcode算法题--二叉搜索树迭代器
  2. 【干货】机器学习中样本比例不平衡的处理方法
  3. P5371-[SNOI2019]纸牌【矩阵乘法】
  4. NOIP 2010 引水入城
  5. CentOS7安装Nginx,全网最快安装教程
  6. Script to Setup NTP/DNS/Powerpolicy for new server
  7. 开源大数据周刊-第50期
  8. MySQL数据库学习2 - 数据库的操作
  9. 悟道web标准:前端性能优化
  10. python 迭代器的方法_python--魔法方法,属性和迭代器
  11. python学习手册四版中文_Python学习手册(第4版) 中文版.pdf 全文免费
  12. docker部署springboot项目
  13. 错觉图片生成实验 - 闪现的绿点
  14. Ubuntu连接不上网络问题的解决方法
  15. 好扑科技技术副总裁戎朋:从海豚浏览器服务器端研发主管到区块链,揭秘区块链技术之路...
  16. smplayer 字幕!解决smplayer字幕乱码的方法
  17. Java String的intern方法
  18. 怎么制作区域分布图,怎么做网点分布图
  19. PSnbsp;07替换颜色
  20. 计算机基础及photoshop应用试题,计算机基础及Photoshop应用选择题(计算机一级B考试卷).doc...

热门文章

  1. 手机php转换txt,PHP 实现的将图片转换为TXT
  2. python周末列表的表示形式合并_Python 列表合并题
  3. python链接mysql 判断是否成功_【初学python】使用python连接mysql数据查询结果并显示...
  4. ni visa pci_CHINACOAT 2019“推荐品牌”赫普菲乐|PCI可名文化出品
  5. linux mysql 无法识别,Linux下MySQL 5.7.23无法远程连接解决方案
  6. qchart折现图_Qt Charts 动态实时折线图绘制
  7. mysql 选项_mysql常用选项
  8. 1、使用库函数计算两个向量的夹角
  9. PCL :K-d tree 2 结构理解
  10. 优达学城python项目P1:搜索和探索近地天体(NEOs)