Spring Boot 动态添加定时任务

  • 实现目标
    • 第一种定时任务实现方式-注解
    • ScheduledTaskRegistrar(注册类)
    • ScheduledAnnotationBeanPostProcessor
    • 动态添加/删除任务实现

实现目标

应用程序在运行期间动态添加、删除定时任务。

第一种定时任务实现方式-注解

@Configuration
@EnableScheduling
public class DemoTask {/*** TODO: 每5秒执行一次* @author FantasticTears* @date 2020/9/25*/@Scheduled(cron = "*/5 * * * * *")public void cronTask() {System.out.println("每5秒执行一次");}
}

注解@Configuration告诉Spring启动时加载该类
注解@EnableScheduling启用计划任务
注解@Scheduled代表具体要执行的任务
Spring 具体加载机制和实现原理请自行研究Spring源码

很明显这种实现方式不符合本文的实现目标,因为这种任务在编译的时候间隔时间和实现的功能已经确定了。说这种实现方式目的是为了引出下一个话题ScheduledTaskRegistrar(注解@EnableScheduling源码上有注释)

ScheduledTaskRegistrar(注册类)

该类总共实现了三个接口ScheduledTaskHolder、InitializingBean、DisposableBean
主要接口是:InitializingBean

public interface InitializingBean {/*** Invoked by the containing {@code BeanFactory} after it has set all bean properties* and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc.* <p>This method allows the bean instance to perform validation of its overall* configuration and final initialization when all bean properties have been set.* @throws Exception in the event of misconfiguration (such as failure to set an* essential property) or if initialization fails for any other reason*/void afterPropertiesSet() throws Exception;}

该接口是Spring Bean 工厂完成Bean的创建工作后调用的一个方法,俗称Bean后置处理器。
这个类里边维护了应用程序所有的定时任务,大家可以去看下这个类的源码,具体的我就不再赘述了。
核心看下这个方法的实现afterPropertiesSet,这个方法会加载和初始化一下成员变量。

ScheduledAnnotationBeanPostProcessor

该类是通过查找ScheduledTaskRegistrar的引用找到的一个类,通过名称我们知道,该类就是处理注解Scheduled的具体实现。通过源码分析,其中有个方法finishRegistration,这个方法最后一行就调用了接口InitializingBeanafterPropertiesSet方法。

动态添加/删除任务实现

通过以上对Spring源码的分析我们总结出一个信息,那就是我们只要能拿到ScheduledTaskRegistrar对象,通过调用该对象的一些添加方法,最后调用一下afterPropertiesSet我们就能实现动态添加/删除任务的目标了。那么如何那到ScheduledTaskRegistrar对象呢,其实在注解EnableScheduling的注释里边已经有Demo了,实现SchedulingConfigurer接口即可。

@Configuration
public class DynamicTask implements SchedulingConfigurer {private static ScheduledTaskRegistrar scheduledTaskRegistrar;@Overridepublic void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {log.info("定时任务注册器:{}", scheduledTaskRegistrar);DynamicTask.scheduledTaskRegistrar = scheduledTaskRegistrar;}/*** TODO: 添加定时任务* @author FantasticTears* @date 2020/9/24*/public static void addScheduledTask(StudyTask studyTask, Check check) {List<CronTask> cronTaskList = scheduledTaskRegistrar.getCronTaskList();cronTaskList.forEach(v -> {if(v.getRunnable() instanceof StudyTask) {if(check.check((StudyTask) v.getRunnable())) {log.info("任务【{}】已在执行计划中!移除该任务并从新添加!", ((StudyTask) v.getRunnable()).getLearnTaskId());cronTaskList.remove(v);}}});if(studyTask.hasTask()) {scheduledTaskRegistrar.addCronTask(studyTask, "*/10 * * * * ?");scheduledTaskRegistrar.afterPropertiesSet();}}
}

特别注意

List<CronTask> cronTaskList = scheduledTaskRegistrar.getCronTaskList();cronTaskList.forEach(v -> {if(v.getRunnable() instanceof StudyTask) {if(check.check((StudyTask) v.getRunnable())) {log.info("任务【{}】已在执行计划中!移除该任务并从新添加!", ((StudyTask) v.getRunnable()).getLearnTaskId());cronTaskList.remove(v);}}});

这个代码在运行时会抛异常,写在这里就是给大家一个警示,删除任务不能通过这种方式实现,具体原因大家看下getCronTaskList这个方法的实现就知道了。
那么如何实现删除已经添加过的任务呢。答案是不能删除,只能取消执行

scheduledTaskRegistrar.getScheduledTasks().forEach(v -> {if(v.getTask() instanceof CronTask) {Task task = v.getTask();if(task.getRunnable() instanceof StudyTask) {if(check.check((StudyTask) task.getRunnable())) {log.info("任务【{}】已在执行计划中!移除该任务并从新添加!", ((StudyTask) task.getRunnable()).getLearnTaskId());v.cancel();}}}});

至此Spring Boot 定时任务动态添加/删除目标已完成!

结语。1


  1. Spring 源码我本身研究的也不多,有什么不对的地方欢迎大家提出,感谢大家的支持。 ↩︎

Spring Boot 动态添加/删除定时任务相关推荐

  1. Quartz 分布式定时任务动态添加删除定时任务

    首先对于Quartz的原理和使用这里不再做赘述和讲解,相信大家可以自信查阅文档进行使用.先说一下个人的这个使用背景:项目中需要引入定时任务,框架是springcloud分布式系统然后调研之后决定引入Q ...

  2. Spring Boot教程(二十):Spring Boot使用String Task定时任务

    一.JAVA常见的几种定时任务比较 Timer:jdk自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让程序按照某一个频度执行, ...

  3. spring boot 动态切换数据源实现多租户开发

    之前的文章有介绍过spring boot 动态切换数据源spring boot 动态切换数据源(数据源信息从数据库中读取)_lgq2016的博客-CSDN博客,今天简单介绍一下动态数据源切换实战,主要 ...

  4. jQuery使用toggleClass方法动态添加删除Class样式的方法

    本文实例讲述了jQuery使用toggleClass方法动态添加删除Class样式的方法.分享给大家供大家参考.具体分析如下: jQuery通过toggleClass方法动态添加删除Class,一次执 ...

  5. 使用API动态添加删除菜单项

    使用API动态添加删除菜单项 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, ...

  6. android仿微信发布动态功能,Android GridView扩展仿微信微博发图动态添加删除图片功能.pdf...

    Android GridView扩扩展展仿仿微微信信微微博博发发图图动动态态添添加加删删除除图图片片功功能能 这篇文章主要为大家详细介绍了Android GridView扩展仿微信微博发图动态添加删除 ...

  7. 动态添加/删除HTML元素

    动态添加/删除HTML元素 <HTML> <HEAD> <title>动态添加/删除HTML元素</title> <style type=&quo ...

  8. Spring Boot 动态修改定时任务cron参数

    动态修改定时任务cron参数 不需要重启应用就可以动态的改变Cron表达式的值不能使用@Scheduled(cron = "${jobs.cron}")实现 动态定时任务类Dyna ...

  9. Spring boot 集成 Elastic-job 实现定时任务

    1. 介绍 当前主流的分布式任务调度: feature quartz elastic-job xxl-job antares opencron 依赖 mysql jdk1.7+, zookeeper ...

  10. Spring Boot 动态数据源(Spring 注解数据源)

    本文实现案例场景: 某系统除了需要从自己的主要数据库上读取和管理数据外,还有一部分业务涉及到其他多个数据库,要求可以在任何方法上可以灵活指定具体要操作的数据库. 为了在开发中以最简单的方法使用,本文基 ...

最新文章

  1. 2021年大数据Flink(三十三):​​​​​​​Table与SQL相关概念
  2. Python培训教程之Python基础知识点梳理
  3. pxe+kickstart实现无人值守网络安装rhel5.4
  4. linux图形界面编程基本知识
  5. 板邓:【WordPress文件解读】wp-config.php
  6. Java程序员面试时要注意的一些问题
  7. mysql 内置功能 存储过程介绍
  8. org.tinygroup.databasebuinstaller-数据库结构及元数据自动创建
  9. 变量存储list python_Python变量类型(八)
  10. 你需要的阿里开源内核诊断工具:diagnose-tools
  11. 单例设计模式(懒汉式,饿汉式)
  12. 第九课 go的循环语句
  13. 军用计算机通用规范测试试验,军用装备环境可靠性试验项目表
  14. tcl语言读取文件一行_TCL语言(九) 路径和文件
  15. 无需教师端极域电子教室的反控制实现
  16. 微信小程序项目实例——打卡时钟
  17. 批量删除新浪微博关注
  18. Studio 3T 破解 mogodb
  19. PremierePR2019CC Beat Edit 安装好之后打不开?Pr下载模板安装后不能使用?Pr全屏预览?此效果需要GPU加速?小清新lut?
  20. Windows取证一

热门文章

  1. 1路编码器脉冲计数器或2路DI高速计数器,Modbus RTU模块 WJ150
  2. ubuntu搭建php运行环境
  3. GO语言实现用户注册方法(互亿无线)
  4. 销售书籍_我们的5合1图书销售又来了!
  5. mysql常用数据库连接池_Java主流常用的数据库连接池
  6. 珠峰高 8848 米,一张纸 0.01 米,这张纸对折多少次后高度超过珠峰
  7. 【转载】OFFICE使用技巧FAQ宝典
  8. 天正对应cad版本_天正建筑t20适用哪个版本cad
  9. java中isolate时间_Dart异步编程:Isolate和事件循环
  10. 最新版 Whatsapp 官网下载安装