第4章 Spring 定时任务

在开发系统时,有时候我们会碰到一些需求,需要由定时任务来完成。SpringBoot开启定时任务很简单。由 @EnableScheduling@Scheduled 来完成。

启动
@SpringBootApplication
@EnableScheduling
public class DatApplication {
    public static void main(String[] args) {
        SpringApplication.run(DatApplication.class, args);
    }
}
定时任务
@Component
@Slf4j
public class TestTask {
    
    @Scheduled(cron = "0 0 5 * * ?")
    public void scheduledTask() {
        System.out.println("定时任务执行了");
    }
}

注意点:@Scheduled 注解的方法不能为 priavte、不能带参数。

扩展点

默认定时任务配置线程池核心大小为1,我可以自己配置定时任务线程池。

@Configuration
public class TaskConfig {

    @Bean
    public SchedulingConfigurer schedulingConfigurer() {
        return taskRegistrar -> {
            ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("task-schedule-pool-%d").build();
            ThreadPoolExecutor taskPool = new ScheduledThreadPoolExecutor(5, threadFactory, new ThreadPoolExecutor.CallerRunsPolicy());
            taskPool.setMaximumPoolSize(20);
            taskPool.setKeepAliveTime(20, TimeUnit.SECONDS);
            taskRegistrar.setScheduler(taskPool);
        };
    }
}
源码
@EnableScheduling的作用

@EnableScheduling 注解主要用来导入配置类 SchedulingConfiguration。那 SchedulingConfiguration 类又有什么有呢。

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

SchedulingConfiguration 是个配置类,用来配置定时任务解析类 ScheduledAnnotationBeanPostProcessor

@Configuration(
    proxyBeanMethods = false
)
@Role(2)
public class SchedulingConfiguration {
    public SchedulingConfiguration() {
    }

    @Bean(
        name = {"org.springframework.context.annotation.internalScheduledAnnotationProcessor"}
    )
    @Role(2)
    public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
        return new ScheduledAnnotationBeanPostProcessor();
    }
}
ScheduledAnnotationBeanPostProcessor 的作用

ScheduledAnnotationBeanPostProcessor 是一个后置处理类,实现了 BeanPostProcessor 接口,该类主要用来解析有 @Scheduled 注解的类。在方法 postProcessAfterInitialization 内进行解析,主要逻辑是:找到有 @Scheduled 注解的标记的方法(可以有多个),然后把 @Scheduled 标记的方法解析成 任务CronTaskFixedDelayTaskFixedRateTask),最后把这些 任务 交给 ScheduledTaskRegistrar 处理。

public Object postProcessAfterInitialization(Object bean, String beanName) {
    // bean不属于以下三种类型
    if (!(bean instanceof AopInfrastructureBean) && !(bean instanceof TaskScheduler) && !(bean instanceof ScheduledExecutorService)) {
        	// 获取bean的原始Class,bean有可能是被代理的。
            Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean);
        	// bean类必须有 @Schedules注解
            if (!this.nonAnnotatedClasses.contains(targetClass) && AnnotationUtils.isCandidateClass(targetClass, Arrays.asList(Scheduled.class, Schedules.class))) {
                // 获取被@Schedules标记的方法,一个方法可以被多个@Schedules标记
                // @Schedules注解是可重复的
                Map<Method, Set<Scheduled>> annotatedMethods = MethodIntrospector.selectMethods(targetClass, (method) -> {
                    Set<Scheduled> scheduledAnnotations = AnnotatedElementUtils.getMergedRepeatableAnnotations(method, Scheduled.class, Schedules.class);
                    return !scheduledAnnotations.isEmpty() ? scheduledAnnotations : null;
                });
                if (annotatedMethods.isEmpty()) {
                    this.nonAnnotatedClasses.add(targetClass);
                    if (this.logger.isTraceEnabled()) {
                        this.logger.trace("No @Scheduled annotations found on bean class: " + targetClass);
                    }
                } else {
                    // 遍历,并Method和@Scheduled封装成任务
                    annotatedMethods.forEach((method, scheduledAnnotations) -> {
                        scheduledAnnotations.forEach((scheduled) -> {
                            // 解析任务
                            this.processScheduled(scheduled, method, bean);
                        });
                    });
                    if (this.logger.isTraceEnabled()) {
                        this.logger.trace(annotatedMethods.size() + " @Scheduled methods processed on bean '" + beanName + "': " + annotatedMethods);
                    }
                }
            }

            return bean;
        } else {
            return bean;
        }
}
执行流

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值