首先,使@Scheduled生效的注解是
@EnableScheduling
可以标注在配置类或者Application类上.
/ * @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
* @see Scheduled
* @see SchedulingConfiguration
* @see SchedulingConfigurer
* @see ScheduledTaskRegistrar
* @see Trigger
* @see ScheduledAnnotationBeanPostProcessor
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(SchedulingConfiguration.class)
@Documented
public @interface EnableScheduling {
}
这里只引入了SchedulingConfiguration.class这个类,这个类也是配置类.
这个配置类里又实例化了ScheduledAnnotationBeanPostProcessor
new ScheduledAnnotationBeanPostProcessor()和ScheduledTaskRegistrar
new ScheduledTaskRegistrar();
这个ScheduledAnnotationBeanPostProcessor类是@Scheduled注解的实际处理类.
ScheduledAnnotationBeanPostProcessor实现了BeanPostProcessor接口.
org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor#postProcessAfterInitialization方法处理了校验信息,然后调用
org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor#processScheduled方法处理任务,这里有三种task,分别是CronTask,FixedDelayTask,FixedRateTask.分别用三种方法去处理task.
tasks.add(this.registrar.scheduleCronTask(new CronTask(runnable, new CronTrigger(cron, timeZone))));
tasks.add(this.registrar.scheduleFixedDelayTask(new FixedDelayTask(runnable, fixedDelay, initialDelay)));
tasks.add(this.registrar.scheduleFixedRateTask(new FixedRateTask(runnable, fixedRate, initialDelay)));
ApplicationContext容器初始化的时候把所有的任务都放到Map容器中,并且配置好了执行规则.
上面我们知道实例化了ScheduledTaskRegistrar对象,在afterPropertiesSet时,执行了执行器
TaskScheduler的初始化.以及一些初始任务的执行
/**
* Calls {@link #scheduleTasks()} at bean construction time.
*/
@Override
public void afterPropertiesSet() {
scheduleTasks();
}
/**
* Schedule all registered tasks against the underlying
* {@linkplain #setTaskScheduler(TaskScheduler) task scheduler}.
*/
@SuppressWarnings("deprecation")
protected void scheduleTasks() {
if (this.taskScheduler == null) {
this.localExecutor = Executors.newSingleThreadScheduledExecutor();
this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
}
if (this.triggerTasks != null) {
for (TriggerTask task : this.triggerTasks) {
addScheduledTask(scheduleTriggerTask(task));
}
}
if (this.cronTasks != null) {
for (CronTask task : this.cronTasks) {
addScheduledTask(scheduleCronTask(task));
}
}
if (this.fixedRateTasks != null) {
for (IntervalTask task : this.fixedRateTasks) {
addScheduledTask(scheduleFixedRateTask(task));
}
}
if (this.fixedDelayTasks != null) {
for (IntervalTask task : this.fixedDelayTasks) {
addScheduledTask(scheduleFixedDelayTask(task));
}
}
}
有了初始化好的执行器,并且有了配置规则,那么@Scheduled任务就按部就班执行就好了.
org.springframework.scheduling.concurrent.ReschedulingRunnable#run
然后会调用自己的方法.每执行结束就计算下一次执行时间.如此周而复始.