一
:
前言
本文主要介绍Spring Boot中使用定时任务的执行原理。
二:@Scheduled使用方式
定时任务注解为@Scheduled。使用方式举例如下:
@Scheduled(cron = "0 0 16 * * ?")
public void depositJob() {
}
@Scheduled(fixedRate = 1000 * 60)
public void job2() {
}
@Scheduled(fixedRate = 1000 * 60,initialDelay = 1000)
public void updatePayRecords() {
}
备注:具体参数可以参考“spring-context-4.2.4.RELEASE.jar”下面的“org.springframework.scheduling.annotation.Scheduled"类。
三
:
@Scheduled代码执行原理说明
简要介绍:
spring在初始化bean后,通过“postProcessAfterInitialization”拦截到所有的用到“@Scheduled”注解的方法,并解析相应的的注解参数,放入“定时任务列表”等待后续处理;
之后再“定时任务列表”中统一执行相应的定时任务(任务为顺序执行,先执行cron,之后再执行fixedRate)。
重要代码如下:
@Override
public Object postProcessAfterInitialization(final Object bean, String beanName) {
for (Map.EntrySet> entry : annotatedMethods.entrySet()) {
Method method = entry.getKey();
for (Scheduled scheduled : entry.getValue()) {
processScheduled(scheduled, method, bean);
}
}
}
return bean;
}
第二步:将对应类型的定时器放入相应的“定时任务列表”中。//说明:ScheduledAnnotationBeanPostProcessor继承BeanPostProcessor。//获取scheduled类参数,之后根据参数类型、相应的延时时间、对应的时区放入不同的任务列表中
protected void processScheduled(Scheduled scheduled, Method method, Object bean) {
String cron = scheduled.cron();
if (StringUtils.hasText(cron)) {
Assert.isTrue(initialDelay == -1, "'initialDelay' not supported for cron triggers");
processedSchedule = true;
String zone = scheduled.zone();
this.registrar.addCronTask(new CronTask(runnable, new CronTrigger(cron, timeZone)));
}
long fixedRate = scheduled.fixedRate();
String fixedDelayString = scheduled.fixedDelayString();
if (fixedRate >= 0) {
Assert.isTrue(!processedSchedule, errorMessage);
processedSchedule = true;
this.registrar.addFixedRateTask(new IntervalTask(runnable, fixedRate, initialDelay));
}
String fixedRateString = scheduled.fixedRateString();
if (StringUtils.hasText(fixedRateString)) {
Assert.isTrue(!processedSchedule, errorMessage);
processedSchedule = true;
if (this.embeddedValueResolver != null) {
fixedRateString = this.embeddedValueResolver.resolveStringValue(fixedRateString);
}
fixedRate = Long.parseLong(fixedRateString);
this.registrar.addFixedRateTask(new IntervalTask(runnable, fixedRate, initialDelay));
}
}
return bean;
}
第三步:执行相应的定时任务。说明:定时任务先执行corn,判断定时任务的执行时间,计算出相应的下次执行时间,放入线程中,到相应的时间后进行执行。之后执行按“频率”(fixedRate)执行的定时任务,直到所有任务执行结束。
protected void scheduleTasks() {
if (this.cronTasks != null) {
for (CronTask task : this.cronTasks) {
this.scheduledFutures.add(this.taskScheduler.schedule(
task.getRunnable(), task.getTrigger()));
}
}
if (this.fixedRateTasks != null) {
for (IntervalTask task : this.fixedRateTasks) {
if (task.getInitialDelay() > 0) {
Date startTime = new Date(now + task.getInitialDelay());