0 40 17 * 17点40执行 0 0/5 5秒执行一次
// 依次加载所有的实现Scheduled注解的类方法public Object postProcessAfterInitialization(final Object bean, String beanName) {Class<?> targetClass = AopUtils.getTargetClass(bean);ReflectionUtils.doWithMethods(targetClass, new MethodCallback() {public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {Iterator var2 = AnnotationUtils.getRepeatableAnnotation(method, Schedules.class, Scheduled.class).iterator();while(var2.hasNext()) {Scheduled scheduled = (Scheduled)var2.next();ScheduledAnnotationBeanPostProcessor.this.processScheduled(scheduled, method, bean);}}});return bean;}
protected void processScheduled(Scheduled scheduled, Method method, Object bean) {try {//该方法不能有returnAssert.isTrue(Void.TYPE.equals(method.getReturnType()), "Only void-returning methods may be annotated with @Scheduled");//该方法不能有入参Assert.isTrue(method.getParameterTypes().length == 0, "Only no-arg methods may be annotated with @Scheduled");if (AopUtils.isJdkDynamicProxy(bean)) {try {method = bean.getClass().getMethod(method.getName(), method.getParameterTypes());} catch (SecurityException var21) {ReflectionUtils.handleReflectionException(var21);} catch (NoSuchMethodException var22) {throw new IllegalStateException(String.format("@Scheduled method '%s' found on bean target class '%s', but not found in any interface(s) for bean JDK proxy. Either pull the method up to an interface or switch to subclass (CGLIB) proxies by setting proxy-target-class/proxyTargetClass attribute to 'true'", method.getName(), method.getDeclaringClass().getSimpleName()));}}//真正执行的RunnableRunnable runnable = new ScheduledMethodRunnable(bean, method);boolean processedSchedule = false;String errorMessage = "Exactly one of the 'cron', 'fixedDelay(String)', or 'fixedRate(String)' attributes is required";// Determine initial delaylong initialDelay = scheduled.initialDelay();String initialDelayString = scheduled.initialDelayString();if (StringUtils.hasText(initialDelayString)) {Assert.isTrue(initialDelay < 0L, "Specify 'initialDelay' or 'initialDelayString', not both");if (this.embeddedValueResolver != null) {initialDelayString = this.embeddedValueResolver.resolveStringValue(initialDelayString);}try {initialDelay = (long)Integer.parseInt(initialDelayString);} catch (NumberFormatException var20) {throw new IllegalArgumentException("Invalid initialDelayString value \"" + initialDelayString + "\" - cannot parse into integer");}}// Check cron expressionString cron = scheduled.cron();if (StringUtils.hasText(cron)) {Assert.isTrue(initialDelay == -1L, "'initialDelay' not supported for cron triggers");processedSchedule = true;String zone = scheduled.zone();if (this.embeddedValueResolver != null) {cron = this.embeddedValueResolver.resolveStringValue(cron);zone = this.embeddedValueResolver.resolveStringValue(zone);}TimeZone timeZone;if (StringUtils.hasText(zone)) {timeZone = StringUtils.parseTimeZoneString(zone);} else {timeZone = TimeZone.getDefault();}//放入cron任务列表中(不执行)this.registrar.addCronTask(new CronTask(runnable, new CronTrigger(cron, timeZone)));}if (initialDelay < 0L) {initialDelay = 0L;}// Check fixed delaylong fixedDelay = scheduled.fixedDelay();if (fixedDelay >= 0L) {Assert.isTrue(!processedSchedule, errorMessage);processedSchedule = true;this.registrar.addFixedDelayTask(new IntervalTask(runnable, fixedDelay, initialDelay));}String fixedDelayString = scheduled.fixedDelayString();if (StringUtils.hasText(fixedDelayString)) {Assert.isTrue(!processedSchedule, errorMessage);processedSchedule = true;if (this.embeddedValueResolver != null) {fixedDelayString = this.embeddedValueResolver.resolveStringValue(fixedDelayString);}try {fixedDelay = (long)Integer.parseInt(fixedDelayString);} catch (NumberFormatException var19) {throw new IllegalArgumentException("Invalid fixedDelayString value \"" + fixedDelayString + "\" - cannot parse into integer");}this.registrar.addFixedDelayTask(new IntervalTask(runnable, fixedDelay, initialDelay));}//执行频率类型(long类型)long fixedRate = scheduled.fixedRate();if (fixedRate >= 0L) {Assert.isTrue(!processedSchedule, errorMessage);processedSchedule = true;this.registrar.addFixedRateTask(new IntervalTask(runnable, fixedRate, initialDelay));}//执行频率类型(字符串类型,不接收参数计算如:600*20)String fixedRateString = scheduled.fixedRateString();if (StringUtils.hasText(fixedRateString)) {Assert.isTrue(!processedSchedule, errorMessage);processedSchedule = true;if (this.embeddedValueResolver != null) {fixedRateString = this.embeddedValueResolver.resolveStringValue(fixedRateString);}try {fixedRate = (long)Integer.parseInt(fixedRateString);} catch (NumberFormatException var18) {throw new IllegalArgumentException("Invalid fixedRateString value \"" + fixedRateString + "\" - cannot parse into integer");}//放入FixedRate任务列表中(不执行)this.registrar.addFixedRateTask(new IntervalTask(runnable, fixedRate, initialDelay));}Assert.isTrue(processedSchedule, errorMessage);} catch (IllegalArgumentException var23) {throw new IllegalStateException("Encountered invalid @Scheduled method '" + method.getName() + "': " + var23.getMessage());}}
protected void scheduleTasks() {
long now = System.currentTimeMillis();
if (this.taskScheduler == null) {
//使用newSingleThreadScheduledExecutor执行
this.localExecutor = Executors.newSingleThreadScheduledExecutor();
this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
}
if (this.triggerTasks != null) {
for (TriggerTask task : triggerTasks) {
//顺序执行相应的Cron
this.scheduledFutures.add(this.taskScheduler.schedule(
task.getRunnable(), task.getTrigger()));
}
}
if (this.cronTasks != null) {
for (CronTask task : cronTasks) {
this.scheduledFutures.add(this.taskScheduler.schedule(
task.getRunnable(), task.getTrigger()));
}
}
//顺序执行所有的“fixedRate”定时任务(无延迟,也就是说initialDelay参数为空),因为无延迟,
//所以定时任务会直接执行一次,执行任务完成后,会将下次执行任务的时间放入delayedExecute中等待下次执行。
if (this.fixedRateTasks != null) {
for (IntervalTask task : fixedRateTasks) {
if (task.getInitialDelay() > 0) {
Date startTime = new Date(now + task.getInitialDelay());
this.scheduledFutures.add(this.taskScheduler.scheduleAtFixedRate(
task.getRunnable(), startTime, task.getInterval()));
}
else {
this.scheduledFutures.add(this.taskScheduler.scheduleAtFixedRate(
task.getRunnable(), task.getInterval()));
}
}
}
//顺序执行所有的“fixedRate”定时任务(有延迟,也就是说initialDelay参数不为空)
if (this.fixedDelayTasks != null) {
for (IntervalTask task : fixedDelayTasks) {
if (task.getInitialDelay() > 0) {
Date startTime = new Date(now + task.getInitialDelay());
this.scheduledFutures.add(this.taskScheduler.scheduleWithFixedDelay(
task.getRunnable(), startTime, task.getInterval()));
}
else {
this.scheduledFutures.add(this.taskScheduler.scheduleWithFixedDelay(
task.getRunnable(), task.getInterval()));
}
}
}
}
//runnable的run方法
//每次执行定时任务结束后,会先设置下下次定时任务的执行时间,以此来确认下次任务的执行时间。
public void run() {
try {
ReflectionUtils.makeAccessible(this.method);
this.method.invoke(this.target);
} catch (InvocationTargetException var2) {
ReflectionUtils.rethrowRuntimeException(var2.getTargetException());
} catch (IllegalAccessException var3) {
throw new UndeclaredThrowableException(var3);
}
}
