Spring定时任务自动化:@Scheduled注解的高效使用,有两下子!

举报
bug菌 发表于 2024/07/28 16:39:07 2024/07/28
【摘要】 本专栏致力打造最硬核 Spring Boot 从零基础到进阶系列学习内容,🚀均为全网独家首发,打造精品专栏,专栏持续更新中…欢迎大家订阅持续学习。 如果想快速定位学习,可以看这篇【SpringBoot教程导航帖】,你想学习的都被收集在内,快速投入学习!!两不误。

📣前言

  在自动化和云时代背景下,定时任务成为后端服务中一项不可或缺的功能。Spring框架以其强大的功能,为定时任务的实现提供了优雅的解决方案。@Scheduled注解,作为Spring定时任务支持的核心,允许开发者以一种声明式的方式处理周期性任务。本文将深入探讨@Scheduled注解的高效使用方法,帮助Java开发者轻松实现定时任务的自动化。

  那么,具体如何实现呢?这将又会是干货满满的一期,全程无尿点不废话只抓重点教,具有非常好的学习效果,拿好小板凳准备就坐!希望学习的过程中大家认真听好好学,学习的途中有任何不清楚或疑问的地方皆可评论区留言或私信,bug菌将第一时间给予解惑,那么废话不多说,直接开整!Fighting!!

🌊环境说明

开发工具:IDEA 2021.3
JDK版本: JDK 1.8
Spring Boot版本:2.3.1 RELEASE
Maven版本:3.8.2


🏆本文收录于《Spring Boot从入门到精通》,专门攻坚指数提升,2023 年国内最系统+最强(更新中)。

本专栏致力打造最硬核 Spring Boot 从零基础到进阶系列学习内容,🚀均为全网独家首发,打造精品专栏,专栏持续更新中…欢迎大家订阅持续学习。 如果想快速定位学习,可以看这篇【SpringBoot教程导航帖】,你想学习的都被收集在内,快速投入学习!!两不误。


🌊摘要

  本文详细介绍了Spring框架中的@Scheduled注解,包括其基本用法、配置选项、源码解析、案例分析、应用场景、优缺点分析,以及如何编写测试用例。通过实际代码示例,引导读者深入理解并有效使用@Scheduled注解,提高定时任务的自动化水平。

🌊正文

搭建Spring Boot应用

  首先,我们先创建个基础的Spring Boot项目,如果还不会点这里,此处就不详细赘述啦。

简介

  @Scheduled注解是Spring提供的一种用于简化定时任务实现的机制。它与@EnableScheduling注解配合使用,可以轻松地在Spring应用程序中添加定时任务。

  @Scheduled是Spring框架提供的一个注解,用于在Spring管理的Bean中声明方法为定时任务。通过使用@Scheduled,你可以方便地配置和执行周期性任务,而无需自己编写底层的定时逻辑。

以下是@Scheduled注解的一些关键点:

使用方式

  • 方法级别:将@Scheduled注解直接添加到需要定时执行的方法上。
  • 配置:通过注解的属性来指定执行计划,如固定延迟、固定速率或Cron表达式。

注解属性

  • cron:接受一个Cron表达式,用于复杂的时间设置。
  • fixedRate:任务执行间隔时间(单位为毫秒),如果设置,表示任务在完成上一次执行后等待固定时间再执行。
  • fixedDelay:任务执行后等待固定时间再执行下一次(单位为毫秒),与fixedRate不同,这个间隔是在任务开始时计算的。
  • zone:指定时区,用于Cron表达式中的时间计算。

注意事项

  • 确保Spring应用程序启用了定时任务支持,这通常通过在配置类上添加@EnableScheduling注解来实现。
  • 考虑任务执行的异常处理,确保应用程序的稳定性。
  • 定时任务的执行计划应根据实际需求合理配置,避免资源浪费。

测试

  测试定时任务可能比较困难,因为它们依赖于时间。可以使用Mockito等工具来模拟时间依赖,或者编写集成测试来验证任务的行为。

  通过@Scheduled注解,Spring大大简化了周期性任务的管理,使得开发者可以更专注于业务逻辑的实现。

源码解析

  @Scheduled注解允许开发者通过简单的注解配置,指定方法的执行计划。以下是@Scheduled注解的基本结构:

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scheduled {
    String cron() default "";

    long fixedRate() default 0;

    long fixedDelay() default 0;

    String zone() default "";
}
  • cron(): 用于指定cron表达式,提供更灵活的执行计划定义。
  • fixedRate(): 以固定的速率执行任务,单位为毫秒。
  • fixedDelay(): 在前一个任务执行结束后,等待固定的延迟时间再执行下一个任务,单位为毫秒。
  • zone(): 时区设置,用于指定任务执行的时区。

  接着我将对上述代码进行详细的一个逐句解读,希望能够帮助到同学们,能以更快的速度对其知识点掌握学习,这也是我写此文的初衷,授人以鱼不如授人以渔,只有将其原理摸透,日后应对场景使用,才能得心应手,所以如果有基础的同学,可以略过如下代码分析步骤,然而没基础的同学,还是需要加强对代码的理解,方便你深入理解并掌握其常规使用。

  @Scheduled注解是Spring框架中用于标记应定期执行的方法的注解。以下是对@Scheduled注解源码的详细解析:

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
  • @Target注解指定了@Scheduled可以应用于方法或注解类型。这意味着@Scheduled注解通常用在方法上,但也可以在其他注解中使用。
@Retention(RetentionPolicy.RUNTIME)
  • @Retention注解定义了@Scheduled注解的保留策略。RetentionPolicy.RUNTIME表示注解在运行时保留,可以通过反射获取注解的值。
@Documented
  • @Documented元注解指示该注解应该被包含在JavaDoc中,有助于生成文档时展示这些注解信息。
public @interface Scheduled {
  • 这行代码声明了Scheduled是一个注解类型。
    String cron() default "";
  • cron()方法定义了cron表达式属性。cron表达式用于配置更复杂的定时任务执行计划。如果没有提供cron表达式,则可以使用其他属性如fixedRatefixedDelay
    long fixedRate() default 0;
  • fixedRate()方法定义了固定速率属性。如果指定了非零值,任务将按照这个速率(单位为毫秒)重复执行。
    long fixedDelay() default 0;
  • fixedDelay()方法定义了固定延迟属性。如果指定了非零值,任务将在前一次执行完成后,等待这个延迟(单位为毫秒)再执行。
    String zone() default "";
  • zone()方法定义了时区属性。这个属性允许你为定时任务指定一个时区。如果不指定,默认使用服务器的默认时区。

源码解析的意义

  通过理解@Scheduled注解的源码,我们可以知道:

  • @Scheduled注解提供了多种配置定时任务的方式,包括cron表达式、固定速率和固定延迟。
  • 由于注解在运行时保留,Spring容器可以在启动时通过反射读取这些注解的属性,并根据这些属性来调度任务。
  • 使用@Scheduled注解可以大大简化定时任务的配置和管理。

实际使用示例

  通常在使用@Scheduled注解时,我们会这样使用:

@Component
public class MyScheduledTasks {

    @Scheduled(fixedRate = 1000)
    public void taskWithFixedRate() {
        // 每1000毫秒执行一次
    }

    @Scheduled(fixedDelay = 1000)
    public void taskWithFixedDelay() {
        // 任务执行完成后等待1000毫秒再执行
    }

    @Scheduled(cron = "0 * * * * *")
    public void taskWithCronExpression() {
        // 根据cron表达式执行任务,例如每秒执行一次
    }
}

  在这个示例中,MyScheduledTasks类中定义了三个使用@Scheduled注解的方法,分别展示了固定速率、固定延迟和cron表达式三种不同的定时任务配置方式。

  并附上部分相关注解源码截图,这里我就简单给附上,感兴趣的同学可以扒扒源码,深入去学习下开源框架的设计构思及理念,这也是掌握一个架构的核心目标,但是基础一般或者零基础的同学,建议先从使用上深入,而不是一口吃掉一个胖子,得不偿失。

  实际运用场景展示如下,这也是我日常项目开发中的实操之一,分享给大家看看,仅供参考:

案例分析

  以下是一个使用@Scheduled注解的简单示例:

@Component
public class ScheduledTasks {

    @Scheduled(fixedRate = 5000)
    public void reportCurrentTime() {
        System.out.println("Current time: " + LocalDateTime.now());
    }
}

  在这个例子中,reportCurrentTime方法将每5秒执行一次,打印当前的日期和时间。

  接着我将对上述代码进行详细的一个逐句解读,希望能够帮助到同学们,能以更快的速度对其知识点掌握学习,这也是我写此文的初衷,授人以鱼不如授人以渔,只有将其原理摸透,日后应对场景使用,才能得心应手,所以如果有基础的同学,可以略过如下代码分析步骤,然而没基础的同学,还是需要加强对代码的理解,方便你深入理解并掌握其常规使用。

  这段Java代码演示了如何在Spring框架中使用@Scheduled注解来创建一个简单的定时任务。以下是对这段代码的详细解析:

类定义和注解

  • @Component: 这个注解表明ScheduledTasks类是一个Spring组件,Spring容器应该自动检测并注册这个类为一个Bean。

定时任务方法

  • @Scheduled(fixedRate = 5000): 这个注解声明了一个定时任务,其中fixedRate属性设置为5000,意味着任务将每隔5000毫秒(5秒)执行一次,不考虑上一次任务执行所花费的时间。

方法实现

  • public void reportCurrentTime(): 这是一个公共方法,没有参数和返回值。它被@Scheduled注解标记,因此会按照指定的计划执行。

  • System.out.println("Current time: " + LocalDateTime.now());: 方法体中,使用System.out.println打印当前时间。LocalDateTime.now()获取当前的日期和时间。

应用场景

  这个reportCurrentTime方法可以作为一个简单的定时任务,例如:

  • 定期记录系统状态。
  • 定时发送通知或提醒。
  • 定时执行某些检查或监控任务。

注意事项

  • 确保应用程序中启用了定时任务支持,这通常通过在配置类上添加@EnableScheduling注解来实现。
  • 考虑任务执行的时间间隔和系统负载,避免过度消耗资源。
  • 处理可能的异常,确保定时任务的稳定性。

示例代码扩展

  在实际的Spring Boot应用程序中,可能还需要配置日志记录或其他业务逻辑:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTasks {

    private static final Logger logger = LoggerFactory.getLogger(ScheduledTasks.class);

    @Scheduled(fixedRate = 5000)
    public void reportCurrentTime() {
        logger.info("Current time: {}", LocalDateTime.now());
    }
}

  在这个扩展示例中,我们引入了日志记录,使用Logger来记录当前时间,而不是使用System.out.println。这在生产环境中更为常见,因为它提供了日志级别控制和集成外部日志系统的能力。

应用场景案例列举

  @Scheduled注解通常应用于以下场景:

  • 定期数据备份:定时备份数据库或其他存储的数据。
  • 定时提醒:向用户发送定时通知或提醒。
  • 健康检查:定期检查系统或服务的健康状态。
  • 定时清理:清理临时文件或过期数据。

优缺点分析

  使用@Scheduled注解的优点包括:

  • 声明式配置:简化了定时任务的配置过程。
  • 灵活性:支持多种执行计划定义方式,包括cron表达式和固定延迟/速率。

缺点可能包括:

  • 性能影响:不当的配置可能导致性能问题。
  • 错误处理:需要妥善处理任务执行中的异常。

类代码方法介绍

  使用@Scheduled注解的方法通常遵循以下模式:

@Component
public class MyScheduledTasks {
    // 使用@Scheduled注解的方法
    @Scheduled(cron = "0 * * * * *") // 每秒执行
    public void scheduledTask() {
        // 任务逻辑
    }
}

测试用例

  编写测试用例以验证定时任务的正确性:

public class ScheduledTasksTest {

    public static void main(String[] args) {
        // 创建Spring应用上下文
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(ScheduledTasks.class);
        context.refresh();

        // 获取定时任务的Bean
        ScheduledTasks tasks = context.getBean(ScheduledTasks.class);

        // 模拟等待第一个定时任务执行
        try {
            Thread.sleep(6000); // 等待6秒
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 验证定时任务是否执行
        // 例如,检查日志输出或任务状态
    }
}

  接着我将对上述代码进行详细的一个逐句解读,希望能够帮助到同学们,能以更快的速度对其知识点掌握学习,这也是我写此文的初衷,授人以鱼不如授人以渔,只有将其原理摸透,日后应对场景使用,才能得心应手,所以如果有基础的同学,可以略过如下代码分析步骤,然而没基础的同学,还是需要加强对代码的理解,方便你深入理解并掌握其常规使用。

  这段Java代码是一个简单的测试用例,用于验证使用@Scheduled注解的定时任务是否按预期执行。以下是对这段代码的详细解析:

测试类定义

  • public class ScheduledTasksTest: 定义了一个名为ScheduledTasksTest的测试类。

主函数

  • public static void main(String[] args): Java程序的入口点,这里用作执行测试。

创建Spring应用上下文

  • AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();: 创建了Spring的AnnotationConfigApplicationContext实例,这是用于注册和加载配置类的应用上下文。

  • context.register(ScheduledTasks.class);: 注册了ScheduledTasks类作为配置类。

  • context.refresh();: 刷新应用上下文,这会触发Spring的初始化流程,包括Bean的创建和@PostConstruct注解方法的执行。

获取定时任务的Bean

  • ScheduledTasks tasks = context.getBean(ScheduledTasks.class);: 通过应用上下文获取ScheduledTasks的Bean实例。

模拟等待第一个定时任务执行

  • Thread.sleep(6000);: 使当前线程睡眠6秒,等待定时任务至少执行一次。

验证定时任务是否执行

  • 注释部分// 验证定时任务是否执行: 这里应该添加验证逻辑,例如检查日志输出、数据库记录或其他状态标记,以确保定时任务已经执行。

注意事项

  • 测试用例中的ScheduledTasks类应该包含一些可以观察的行为,比如打印日志或修改状态,以便验证。
  • 由于使用了Thread.sleep,这个测试用例主要用于演示和简单的验证。在实际的自动化测试中,可能需要使用更复杂的方法来等待和验证异步行为。
  • 测试用例应该独立于其他测试,不依赖于外部状态或数据库。

示例代码扩展

在实际的测试中,我们可能需要使用断言来验证定时任务的执行结果:

// 假设ScheduledTasks有一个方法来获取任务执行次数
int executionCount = tasks.getExecutionCount();
assertTrue("The scheduled task did not execute as expected", executionCount > 0);

  这个扩展示例展示了如何通过检查ScheduledTasks类的某个属性(例如执行次数)来验证定时任务是否按预期执行。

  通过上述解析,我们可以看到如何使用Spring的应用上下文来创建和管理Bean,并触发定时任务的执行。通过验证任务的执行结果,可以确保定时任务按预期工作。

小结

  在当今的软件开发实践中,定时任务已成为后端服务中一项极其重要的功能。Spring框架通过其@Scheduled注解,为开发者提供了一种声明式、灵活的方法来处理这类任务。本文通过深入浅出的分析和丰富的实例,全面介绍了@Scheduled注解的使用方法,从基础概念到高级应用,帮助读者构建了对Spring定时任务的深刻理解。

  文章首先对@Scheduled注解的基本用法进行了介绍,包括其注解属性如cronfixedRatefixedDelayzone的详细说明。这些属性为定时任务的配置提供了多样化的选择,使得开发者可以根据具体需求灵活设置任务执行的计划。

  接着,通过实际代码示例,文章展示了如何将@Scheduled注解应用于服务层组件,以及如何通过Spring容器的自动装配功能,简化定时任务的管理。此外,文章还提供了测试用例的编写示例,强调了在开发过程中验证定时任务正确性的重要性。

总结

  @Scheduled注解作为Spring框架中处理定时任务的关键工具,其强大之处在于简化了任务的配置和调度过程。通过本文的学习,我们认识到了合理使用这一注解不仅可以提高开发效率,还能增强代码的可维护性。同时,我们也意识到了在实际开发中需要权衡其使用,避免不当配置对系统性能的影响。

  随着技术的不断演进,@Scheduled注解将继续在Spring生态中发挥重要作用,助力开发者构建更加健壮、灵活的应用程序。让我们持续关注和学习,掌握更多高效工具和最佳实践,共同推动软件行业的发展。


  本文的探讨和分析旨在提供一个全面的视角,帮助开发者深入理解并有效利用@Scheduled注解。希望每位读者都能从中获得有价值的信息和启发,将这些知识应用到实际开发中,不断提升自己的技术水平和专业能力。

… …

  ok,以上就是我这期的全部内容啦,若想学习更多,你可以持续关注我,我会把这个多线程篇系统性的更新,保证每篇都是实打实的项目实战经验所撰。只要你每天学习一个奇淫小知识,日积月累下去,你一定能成为别人眼中的大佬的!功不唐捐,久久为功!

「赠人玫瑰,手留余香」,咱们下期拜拜~~

🌊热文推荐

滴~如下推荐【Spring Boot 进阶篇】的学习大纲,请小伙伴们注意查收。

Spring Boot进阶(01):使用Spring Boot和Redis轻松实现高性能、高可用的缓存服务。

Spring Boot进阶(02):防止程序员疯狂 Debug:快速掌握 Validation 参数校验技巧,让你的代码健康起来!

Spring Boot进阶(03):【实战教程】MyBatis-Plus秒级实现字段自动填充,让你的代码更优雅!

Spring Boot进阶(04):震惊!使用MyBatis-Plus,快速实现自定义SQL分页功能!

Spring Boot进阶(05):Spring Boot与RabbitMQ完美融合,打造高效消息队列服务!

Spring Boot进阶(06):【超详细】Windows10搭建RabbitMQ Server服务端,让你轻松实现消息队列管理!

Spring Boot进阶(07):如何使用EasyPoi实现Java中Excel的导入导出?完整教程请收藏,让你的Excel操作更高效!

Spring Boot进阶(08):使用EasyPoi实现Excel/Word携带图片导出,打造精美的报表

Spring Boot进阶(09):用EasyPoi实现Excel多sheet导入导出,轻松管理海量数据!

Spring Boot进阶(10):「从Excel到PDF,EasyPoi助你一键完美转换!」

Spring Boot进阶(11):实现纯文本转成.csv格式文件,Spring Boot轻松搞定!附完整代码

Spring Boot进阶(12):如何快速获取Excel文件中的Sheet页数量?Spring Boot教程带你一步步实现

Spring Boot进阶(13):如何优雅获取@ApiModelProperty(value = “序列号“, name = “uuid“)中的value值,附源码

Spring Boot进阶(14):Spring Boot高级应用:手把手教你连接数据库并获取指定表结构!一文教会你

Spring Boot进阶(15):用Spring Boot实现动态数据库分页查询表结构信息!

Spring Boot进阶(16):使用Redis实现手机验证码功能,让你的用户注册更加便捷!

Spring Boot进阶(17):Swagger2高级配置:定制header请求头等参数

Spring Boot进阶(18):轻松管理定时任务!Spring Boot@Scheduled让你事半功倍

Spring Boot进阶(19):探索ElasticSearch:如何利用Spring Boot轻松实现高效数据搜索与分析

Spring Boot进阶(20):「打造高性能Web应用」——使用Jetty容器配置Spring Boot

Spring Boot进阶(21):优化Spring Boot应用性能,使用Undertow容器提升响应速度

Spring Boot进阶(22):决战容器之巅:Tomcat vs Undertow!性能对比分析揭秘最佳选择!

Spring Boot进阶(23):终极解决方案!教你实现高效文件上传!

Spring Boot进阶(24):秒传!快速实现高效多文件上传的最佳解决方案

Spring Boot进阶(25):如何写出高效的文件上传单元测试?让你的测试更智能更高效!

Spring Boot进阶(26):从小白到高手,掌握Mybatis中resultType和resultMap的秘密!

Spring Boot进阶(27):Spring Boot进阶(27):Kafka大显身手,快速构建消息驱动应用!(环境搭建+演示)

Spring Boot进阶(28):如何让Spring Boot应用在Linux中以后台服务方式启动,并实现滚动日志查看及保存至实体文件?

Spring Boot进阶(29):如何正确使用Spring Boot注解@PathVariable、@RequestParam和@RequestBody: Postman演示教程

Spring Boot进阶(30):@RestController与@Controller的区别及使用场景详解,附带精彩实战演示

… …

  若想系统性的从0到1的入门进阶学习,可以参考这篇专栏总结《2024最新首发,全网最全 Spring Boot 学习宝典(附思维导图)》本专栏致力打造全网最硬核 Spring Boot 学习及进阶SpringBoot 系列教学内容,🚀均为全网独家首发,致力打造精品硬核干货,专栏永持续更新。欢迎大家订阅学习。一分耕耘一份收获!

  如果想快速定位学习,可以看这篇【一站式教程导航】,你想学习的都被收录系统整理在内,以最快的速度投入并学习掌握!!你值得拥有。

  在入门及进阶之途,我必助你一臂之力,系统性学习,从入门到精通,带你不走弯路,直奔终点!投资自己,性价比永远最高,都这么说了,你还不赶紧来白嫖??

  本文涉及所有源代码,均已上传至GitHub开源,供同学们一对一参考 GitHub传送门,同时,原创开源不易,欢迎给个star🌟,想体验下被🌟的感jio,非常感谢❗

📣文末

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云2023年度十佳博主,掘金多年度人气作者Top40,掘金等各大社区签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿哇。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。