首页 > 其他分享 >@Scheduled注解停止定时任务、@Scheduled设置定时任务不启用、springboot 配置Schedule不启用、SpringBoot动态配置开启关闭定时任务

@Scheduled注解停止定时任务、@Scheduled设置定时任务不启用、springboot 配置Schedule不启用、SpringBoot动态配置开启关闭定时任务

时间:2024-09-24 17:19:55浏览次数:11  
标签:Scheduled schedule 启用 任务 EnableScheduling org 定时

文章目录

在项目中我们可能会遇到这样一个场景,把一个@Schedule注解的定时任务关闭。以下整理一下如何设置@Schedule注解的定时任务不启用。以下内容基于 org.springframework:spring-context:5.3.12.jar进行讲解


以下为测试代码:

package com.demo.schedule;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@EnableScheduling
@Component
@Slf4j
public class ScheduleTest {

    //每5秒执行一次
    @Scheduled(cron = "${schedule.test1Cron}")
    public void test_1() {
        log.info("测试任务1: " + System.currentTimeMillis());
    }

    //每5秒执行一次
    @Scheduled(cron = "${schedule.test2Cron}")
    public void test_2() {
        log.info("测试任务2: " + System.currentTimeMillis());
    }
}

application.properties配置文件:

#定时任务1
schedule.test1Cron= 0/5 * * * * *
#定时任务2
schedule.test2Cron= 0/5 * * * * *

或者application.yml配置文件:

schedule:
  #定时任务1
  test1Cron: "0/5 * * * * *"
  #定时任务2
  test2Cron: "0/5 * * * * *"

注意: properties中不要用双引号否则会报错(因为加双引号读取时会原文输出即把双引号也带上);yml中可加双引号。

执行结果:

2024-09-24 10:03:55.003  INFO 6788 --- [scheduling-1] com.demo.schedule.ScheduleTest: 测试任务1: 1727143435002
2024-09-24 10:03:55.003  INFO 6788 --- [scheduling-1] com.demo.schedule.ScheduleTest: 测试任务2: 1727143435003
2024-09-24 10:04:00.007  INFO 6788 --- [scheduling-1] com.demo.schedule.ScheduleTest: 测试任务1: 1727143440007
2024-09-24 10:04:00.009  INFO 6788 --- [scheduling-1] com.demo.schedule.ScheduleTest: 测试任务2: 1727143440009
2024-09-24 10:04:05.013  INFO 6788 --- [scheduling-1] com.demo.schedule.ScheduleTest: 测试任务2: 1727143445013
2024-09-24 10:04:05.013  INFO 6788 --- [scheduling-1] com.demo.schedule.ScheduleTest: 测试任务1: 1727143445013
2024-09-24 10:04:10.012  INFO 6788 --- [scheduling-1] com.demo.schedule.ScheduleTest: 测试任务1: 1727143450012
2024-09-24 10:04:10.013  INFO 6788 --- [scheduling-1] com.demo.schedule.ScheduleTest: 测试任务2: 1727143450013

一、关闭定时任务

1.1、方法一:注释@EnableScheduling注解

@EnableScheduling注解的意义是开启定时任务,若@EnableScheduling注解被注释,则整个项目中所有@Scheduled注解的定时任务都将关闭。

优点:

  • 可以一次性关闭项目中所有的定时任务

缺点:

  • 实际项目中可能只是想关闭其中一个定时任务不执行。直接注释@EnableScheduling注解会导致整个项目所有@Scheduled注解的定时任务都将关闭。
  • 需要手动注释代码,生产上更多的是想配置化的,方便修改。
package com.demo.schedule;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

//注释@EnableScheduling注解,关闭整个项目所有的定时任务
//@EnableScheduling  
@Component
@Slf4j
public class ScheduleTest {

    //每5秒执行一次
    @Scheduled(cron = "${schedule.test1Cron}")
    public void test_1() {
        log.info("测试任务1: " + System.currentTimeMillis());
    }

    //每5秒执行一次
    @Scheduled(cron = "0/5 * * * * *")
    public void test_2() {
        log.info("测试任务2: " + System.currentTimeMillis());
    }
}

1.1.1、原理

eg1.正常情况下,只要注释掉@EnableScheduling注解即可,原理就是:

  • 注释掉@EnableScheduling就不会@Import(SchedulingConfiguration.class)
  • 就不会注入ScheduledAnnotationBeanPostProcessor这个后置处理器
  • 这个后置处理器就是用来注册执行@Scheduled定时任务的

eg2.注释掉@EnableScheduling无效,还会执行@Scheduled定时任务?

  • 检查是否项目除启动类还有其它配置类用了@EnableScheduling注解
  • 检查有没有引入spring-session-data-redis依赖,RedisHttpSessionConfiguration内部bean使用了@EnableScheduling
  • 据说spring-boot-starter-actuator依赖也会有,但是我没找到

1.2、方法二:不加载ScheduledAnnotationBeanPostProcessor类

此方法与方法一效果一致,关闭所有@Scheduled的定时任务,只是可以通过配置的方式关闭。

其实 @Scheduled 注解,是被一个叫做 ScheduledAnnotationBeanPostProcessor 的类所拦截的,所以我们可以根据配置,决定是否创建这个 bean,如果没有这个 bean,@Scheduled 就不会被拦截,那么定时任务肯定不会执行了,有了这个思路,实现起来就很简单了。需要注意的是:这种方式,启动类上面的 @EnableScheduling 需要去掉。

  1. 注释所有@EnableScheduling注解
  2. application.properties配置文件中添加以下配置
# 关闭所有scheduled定时任务
scheduled.enable = false
#定时任务1
schedule.test1Cron= 0/5 * * * * *
#定时任务2
schedule.test2Cron= 0/5 * * * * *
  1. 创建一个 ScheduledCondtion 类,内容如下:

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class ScheduledCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        System.out.println("配置属性:"+Boolean.valueOf(context.getEnvironment().getProperty("scheduled.enable")));
        //读取配置中的属性
        return Boolean.valueOf(context.getEnvironment().getProperty("scheduled.enable"));
    }
}

这个类的功能很简单,就是去读取配置,然后返回一个 boolean 值。

  1. 创建一个配置类 ScheduledConfig ,内容如下:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor;

@Configuration
public class ScheduledConfig {
    @Conditional(ScheduledCondition.class)
    @Bean
    public ScheduledAnnotationBeanPostProcessor processor() {
        return new ScheduledAnnotationBeanPostProcessor();
    }
}

这个配置就是以 ScheduledCondtion 为条件,决定是否创建 bean。然后,启动项目,定时任务就会执行,如果我们将配置修改为 false,则不会执行。

1.3、方法三:注释@Scheduled注解

@Scheduled注解的意义是指定当前方法为定时任务,若@Scheduled注解被注释,则当前这个方法的定时任务将关闭。

优点:

  • 通过注释@Scheduled注解可以实现单个定时任务的关闭,

缺点:

  • 需要手动注释代码,对于生产环境来说需要提交代码并重新打包,并不友好。
package com.demo.schedule;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@EnableScheduling  
@Component
@Slf4j
public class ScheduleTest {

    //每5秒执行一次
    //注释@Scheduled注解,关闭当前这个定时任务
    //@Scheduled(cron = "${schedule.test1Cron}")
    public void test_1() {
        log.info("测试任务1: " + System.currentTimeMillis());
    }

    //每5秒执行一次
    @Scheduled(cron = "${schedule.test2Cron}")
    public void test_2() {
        log.info("测试任务2: " + System.currentTimeMillis());
    }
}

1.4、方法四:设置@Scheduled注解cron时间不开启(推荐)

@Scheduled注解源码中说明当cron表达式配置为- 时,不执行该定时任务。所以我们可以通过在application.properties文件中设置定时任务时间为-

cron表达式设置为-时在项目启动时就不会把该定时任务添加到任务池中。原理见下方原理分析。

优点:

  • 可配置化,可以在application.properties配置文件中配置时间,不用修改代码。
  • 支持开启/关闭指定的任务

@Scheduled注解源码如下:

/**
 * 标记要调度的方法的注释。 必须准确指定 cron、fixedDelay 或 fixedRate 属性之一。带注释的方法必须没有参数。    
 * 它通常有一个 void 返回类型; 如果不是,则在通过调度程序调用时将忽略返回值。@Scheduled 注解的处理是通过注册
 * 一个 ScheduledAnnotationBeanPostProcessor 来执行的。 这可以手动完成,或者更方便的是,通过 
 * <task:annotation-driven/> 元素或 @EnableScheduling 注释。
 * 此注释可用作元注释以创建具有属性覆盖的自定义组合注释。
 * @since 3.0
 * @see EnableScheduling
 * @see ScheduledAnnotationBeanPostProcessor
 * @see Schedules
 */
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {

	/**
	 * 指示禁用触发器的特殊 cron 表达式值:“-”。
	 * 这主要用于 ${...} 占位符,允许外部禁用相应的计划方法。
	 * 
	 * @since 5.1
	 * @see ScheduledTaskRegistrar#CRON_DISABLED
	 */
	String CRON_DISABLED = ScheduledTaskRegistrar.CRON_DISABLED;

	/**
	 * 一个类似 cron 的表达式,扩展了通常的 UN*X 定义以包括秒、分、小时、月中的某一天、月份和星期几的触发器。
	 * 例如,“0 * * * * MON-FRI”表示工作日每分钟一次(在分钟的顶部 - 第 0 秒)。
	 * 
	 * 从左到右读取的字段解释如下:
	 * <ul>
	 * <li>second</li>
	 * <li>minute</li>
	 * <li>hour</li>
	 * <li>day of month</li>
	 * <li>month</li>
	 * <li>day of week</li>
	 * </ul>
	 * 特殊值“-”表示禁用的 cron 触发器,主要用于由 ${...} 占位符解析的外部指定值。
	 * @return 返回一个可以解析为 cron 计划的表达式
	 * @see org.springframework.scheduling.support.CronSequenceGenerator
	 */
	String cron() default "";

	/**
	 * 将解析 cron 表达式的时区。 默认:""(即使用服务器的本地时区)。
	 * 
	 * @return java.util.TimeZone.getTimeZone(String) 接受的区域 ID,或指示服务器默认时区的空字符串
	 * @since 4.0
	 * @see org.springframework.scheduling.support.CronTrigger#CronTrigger(String, java.util.TimeZone)
	 * @see java.util.TimeZone
	 */
	String zone() default "";

	/**
	 * 在上次调用结束和下一次调用开始之间的固定时间段,单位:毫秒,默认:-1(不延迟)
	 * 
	 * @return 延迟时长,单位:毫秒
	 */
	long fixedDelay() default -1;

	/**
	 * 上次调用的结束和下一次调用的开始之间固定时间间隔字符串,单位:毫秒。 
	 * 
	 * @return 延迟值字符串,单位:毫秒,例如占位符或
	 *         {@link java.time.Duration#parse java.time.Duration} 兼容值
	 * @since 3.2.2
	 */
	String fixedDelayString() default "";

	/**
	 * 在调用之间的固定时间段,单位:毫秒。
	 * 
	 * @return 以毫秒为单位的周期
	 */
	long fixedRate() default -1;

	/**
	 * 在调用之间的固定时间段字符串,单位:毫秒。
	 * 
	 * @return 延迟值字符串,单位:毫秒,例如占位符或 
	 *         {@link java.time.Duration#parse java.time.Duration} 兼容值
	 * @since 3.2.2
	 */
	String fixedRateString() default "";

	/**
	 * 在第一次执行 fixedRate 或 fixedDelay 任务之前延迟的毫秒数。
	 * 
	 * @return 初始延迟值,单位:毫秒
	 * @since 3.2
	 */
	long initialDelay() default -1;

	/**
	 * 在第一次执行 fixedRate 或 fixedDelay 任务之前延迟的毫秒数字符串。
	 * @return 初始延迟值字符串,单位:毫秒,例如占位符或符合 java.time.Duration 的值
	 * @since 3.2.2
	 */
	String initialDelayString() default "";

}
package com.demo.schedule;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@EnableScheduling  
@Component
@Slf4j
public class ScheduleTest {

    //每5秒执行一次
    //在配置文件中将cron时间配置为- 即可关闭当前这个定时任务
    @Scheduled(cron = "${schedule.test1Cron}")
    public void test_1() {
        log.info("测试任务1: " + System.currentTimeMillis());
    }

    //每5秒执行一次
    @Scheduled(cron = "${schedule.test2Cron}")
    public void test_2() {
        log.info("测试任务2: " + System.currentTimeMillis());
    }
}

application.propertites配置文件:

#定时任务1
schedule.test1Cron= -
#定时任务2
schedule.test2Cron= -

1.4.1、原理

@Scheduled注解中有个常量参数CRON_DISABLED值为- ,当配置cron的值为-时,则不加入任务池中,即实现了关闭定时任务。

源码分析见下图:

位置:org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor#processScheduled
在这里插入图片描述

标签:Scheduled,schedule,启用,任务,EnableScheduling,org,定时
From: https://blog.csdn.net/weixin_49114503/article/details/142481485

相关文章

  • 【VMware ESXi】如何查看启用内存分层功能的 ESXi 主机使用了多少 NVMe 内存。
    VMwarevSphere8U3中作为技术预览所引入的功能“内存分层(MemoryTiering)”,相信大家已经在自己的测试或实验环境中应用并验证了,如果你还不知道,请跳转到这篇(把硬盘当内存用?VMware内存分层(MemoryTiering),你值得拥有!)文章了解相关介绍以及如何启用它。需要注意的是,目前在启用内存......
  • SpringBoot使用@Scheduled注解实现定时任务
    SpringBoot使用@Scheduled注解实现定时任务_springbootscheduled注解-CSDN博客 importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.scheduling.annotation.EnableSched......
  • innobackupex定时全备,增量备份,压缩备份,自动同步到远程服务器脚本
    全量备份#!/bin/bash#设置变量mysql_backup_dir=/data/backup/mysql/mysql_username="yours"mysql_password="YOURS"#进入备份目录cd$mysql_backup_dir#生成当前时间戳timeStart=$(date'+%Y%m%d%H%M%S')logfile=full-$timeStart.log#执行全量备份/usr......
  • MySQL主从复制中启用GTID(全局事务标识符)模式
    在MySQL中启用GTID(全局事务标识符)模式进行主从复制涉及几个步骤。GTID为每个事务赋予一个唯一的标识符,从而简化了复制过程和故障恢复。以下是启用GTID模式的基本步骤:首先确保两台数据库目前数据保持一致1.准备工作确保您使用的MySQL版本支持GTID。GTID从MySQL5.6版本开始支持......
  • 14.STM32F103C8T6+CUBEMX+循迹模块(定时器计数、测速)
        学习完b站keysking老师的视频后写了这篇笔记,主要是学习定时器外部时钟。    用的是TIM2(有ETR,TIM3和TIM4都没有)一、cubemx配置(没加无上限计数)1、开TIM2    选了外部时钟模式1,借助从模式ETR1;        下面改数值15是输入滤波器,因为抖动......
  • PGSQL-备份和恢复-增量备份-开启wal归档、并设置定时清理备份之后的wal文件
      一、增量备份定期对数据库做基础备份,再配合WAL的归档日志,可实现再较短时间将数据库恢复 开启WAL归档创建归档目录[root@s101/var/lib/pgsql/13]#lsarchive_walsbackupsscriptswal归档记录 touch pg_archive_logs[root@s101/var/lib/pgsql/13/archive_wals......
  • QT核心模块源码分析:定时器与并发
    QT核心模块源码分析:定时器与并发使用AI技术辅助生成QT界面美化视频课程QT性能优化视频课程QT原理与源码分析视频课程QTQMLC++扩展开发视频课程免费QT视频课程您可以看免费1000+个QT技术视频免费QT视频课程QT统计图和QT数据可视化视频免费看免费QT视频课程QT性能优化......
  • 学习笔记488—Acrobat设置默认页面显示方式为启用滚动
    Acrobat设置默认页面显示方式为启用滚动使用Acrobat每次打开pdf文件总是单页视图模式,需要手动选择“启用滚动”才能单页连续滚动。但是往往再次打开别的pdf文件时,又恢复到单页视图了,还是需要探索一劳永逸的设置方式解决。经过查找找到了解决方案,具体步骤如下。1、打开Acrobat,选择......
  • 正式启用!视爵光旭助力打造华南首座8K XR+VP摄影棚
    视爵光旭x国家超高清视频创新中心华南首个8K超高清XR+VP摄影棚正式启动粤港澳超高清数创园区,是由深圳广电集团·天擎数字、国家超高清视频创新中心、宝视达广告控股合资成立超清数创(深圳)文化科技有限公司共同打造。以“AI+5G+8K”为核心,全面布局影视行业全场景应用产业,打......
  • 【2024华为杯E题】高速公路应急车道启用E题思路+代码+论文
    订阅本专栏,认真钻研,保省级及以上奖项!若无获奖,本博主免费提供任意两份本博客初级版专栏代码!......