Spring 定时任务

使用场景

日常开发中经常有这样的场景,如每隔几秒钟或几分钟去执行一下某段业务代码,或者到达某个时间点去执行某个动作。定时任务通常是处理一些非及时的操作,具有异步性,规律性。

常用的定时任务框架

Quartz

Quartz 准确来说它不单单是一个定时任务框架,而是一个调度框架。它的功能比 Spring 的定时任务功能要强大的多。

Quartz 有强大的调度能力,灵活的应用方式,还具有集群,容错等功能。

Quartz 集群依赖数据库作为调度的中心;貌似官方并没有提供管理后台,用来管理任务。

单机版的 Quartz 和 Spring 定时任务功能差不多。

Spring 定时任务

Spring 定时任务是 Spring 自带的一个定时任务实现;准确的说它只是个定时任务框架,不是一个调度框架,应为不具备调度能力。

Spring 定时任务相对比较简单方便,如果想实现一些简单的任务是一个不错的选择;相对复杂且需要调度,容错,集群的功能不建议使用。

Spring 定时任务也没有管理界面。

Elasticjob

Elasticjob 是当当网开源的一个任务调度框架。

Elasticjob 支持分布式调度协调,弹性扩容缩容,作业分片,失效转移,运维平台等功能。

Elasticjob 依赖 Zookeeper 作为调度中心。

提供有管理后台管理任务。

Elasticjob 更新并不是很活跃,好像有一年多没有更新了。

XXL-JOB

XXL-JOB 是个人开发的一个任务调度平台,功能比较丰富,目前维护也相对活跃。

Spring 定时任务的使用

想要了解一样东西,先从使用开始,以 Spring Boot 为例。

启用定时任务 @EnableScheduling

在启动类上加 @EnableScheduling 表示启动定时任务

@EnableScheduling
@SpringBootApplication
public class AopApplication {
    public static void main(String[] args) {
        SpringApplication.run(AopApplication.class, args);
    }
}

使用 @Scheduled 标识定时任务

在有需要的方法上加入 @Scheduled

延时策略分两大类 一类是根据 cron 表达式,一类是根据延时时间。

注意加@Scheduled 方法不能有返回值和参数,否则启动报错。

/**
 * 该类一定是要托管给 Spring 容器的类 ,否则加 @Scheduled 也没有用
 * 时间单位默认是毫秒
 */
@Service
public class ScheduleTestImpl implements ScheduleTest {

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

    /**
     * 使用 cron 完成定时任务
     */
    @Scheduled(cron = "0/20 * * * * ?")
    private void cron() {
        logger.info("cron");
    }

    /**
     * fixedDelay 上次任务执行完,才会执行下次任务;
     * initialDelay 首次运行延迟时间
     * <p>
     * 这里不会每秒打印一次
     *
     * @throws InterruptedException
     */
    @Scheduled(fixedDelay = 1000, initialDelay = 1000)
    public void fixedDelay() throws InterruptedException {
        logger.info("fixedDelay");
        Thread.sleep(10000);
    }

    /**
     * fixedRate 固定时间运行,不管上次任务是否执行完成
     * initialDelay 首次运行延迟时间
     * <p>
     * 这里会每秒打印一次
     *
     * @throws InterruptedException
     */
    @Scheduled(fixedRate = 1000, initialDelay = 1000)
    public void fixedRate() throws InterruptedException {
        logger.info("fixedRate");
        Thread.sleep(10000);
    }
}

Spring 定时任务主要元素

了解源码前我们先了解一下 Spring 定时任务实现主要元素。

Trigger

Trigger 时间触发器,根据定义的 cron 表达是或者配置的延迟时间获取下次执行时间。

有两个实现类: org.springframework.scheduling.support.CronTrigger 根据 cron 表达式获取下次执行时间;

org.springframework.scheduling.support.PeriodicTrigger 根据延时策略获取下次执行时间。

Task

Task 任务,代表需要执行的操作:

org.springframework.scheduling.config.CronTask 根据 cron 生成的任务;

org.springframework.scheduling.config.IntervalTask 根据延时条件生成的任务;

org.springframework.scheduling.config.TriggerTask 根据 Trigger 生成的任务。

TaskScheduler

TaskScheduler 任务调度器;负责调度,执行 Task 任务。

org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler

org.springframework.scheduling.commonj.TimerManagerTaskScheduler

默认使用 ThreadPoolTaskScheduler 线程池的调度实现。

@EnableScheduling 原理

在启动类上加 @EnableScheduling 表示启用 Spring 的定时任务;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(SchedulingConfiguration.class)
@Documented
public @interface EnableScheduling {

}

@EnableScheduling 通过 @Import导入一个 SchedulingConfiguration 的配置类; @Import 可以将一个配置类或者普通的一个类初始化到 Spring 容器中。

@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class SchedulingConfiguration {

    @Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
        return new ScheduledAnnotationBeanPostProcessor();
    }
}

SchedulingConfiguration 初始化注册了 ScheduledAnnotationBeanPostProcessor ;

Spring 定时任务的主要实现都在 ScheduledAnnotationBeanPostProcessor ;

ScheduledAnnotationBeanPostProcessor 继承了 BeanPostProcessor

简单来说 @EnableScheduling 目的就是为了注册 ScheduledAnnotationBeanPostProcessor 来完成对定时任务的实现。

Spring 定时任务实现的主要思路

我们先了解一下 Spring 定时任务实现的主要思路,对我们了解源码会有很大的帮助。

上面通过 @EnableScheduling 注册了 ScheduledAnnotationBeanPostProcessor ,而 ScheduledAnnotationBeanPostProcessor 继承实现了 BeanPostProcessor

BeanPostProcessor 这是一个容器级别的回调类,Spring 容器初始化的时候会回调这个类,回调的时候可以获取这个类的信息或者修改这个的类实现。

上篇文章我们讲究 AOP 的时候说过这类的作用。学习 Spring 我觉得得先学习 Spring 常见的一些类的作用 如 EmbeddedValueResolverAwareBeanNameAwareBeanFactoryAwareApplicationContextAwareSmartInitializingSingletonBeanPostProcessor 等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值