0 40 17 * 17点40执行 0 0/5 5秒执行一次

    1. // 依次加载所有的实现Scheduled注解的类方法
    2. public Object postProcessAfterInitialization(final Object bean, String beanName) {
    3. Class<?> targetClass = AopUtils.getTargetClass(bean);
    4. ReflectionUtils.doWithMethods(targetClass, new MethodCallback() {
    5. public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
    6. Iterator var2 = AnnotationUtils.getRepeatableAnnotation(method, Schedules.class, Scheduled.class).iterator();
    7. while(var2.hasNext()) {
    8. Scheduled scheduled = (Scheduled)var2.next();
    9. ScheduledAnnotationBeanPostProcessor.this.processScheduled(scheduled, method, bean);
    10. }
    11. }
    12. });
    13. return bean;
    14. }
    1. protected void processScheduled(Scheduled scheduled, Method method, Object bean) {
    2. try {
    3. //该方法不能有return
    4. Assert.isTrue(Void.TYPE.equals(method.getReturnType()), "Only void-returning methods may be annotated with @Scheduled");
    5. //该方法不能有入参
    6. Assert.isTrue(method.getParameterTypes().length == 0, "Only no-arg methods may be annotated with @Scheduled");
    7. if (AopUtils.isJdkDynamicProxy(bean)) {
    8. try {
    9. method = bean.getClass().getMethod(method.getName(), method.getParameterTypes());
    10. } catch (SecurityException var21) {
    11. ReflectionUtils.handleReflectionException(var21);
    12. } catch (NoSuchMethodException var22) {
    13. 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()));
    14. }
    15. }
    16. //真正执行的Runnable
    17. Runnable runnable = new ScheduledMethodRunnable(bean, method);
    18. boolean processedSchedule = false;
    19. String errorMessage = "Exactly one of the 'cron', 'fixedDelay(String)', or 'fixedRate(String)' attributes is required";
    20. // Determine initial delay
    21. long initialDelay = scheduled.initialDelay();
    22. String initialDelayString = scheduled.initialDelayString();
    23. if (StringUtils.hasText(initialDelayString)) {
    24. Assert.isTrue(initialDelay < 0L, "Specify 'initialDelay' or 'initialDelayString', not both");
    25. if (this.embeddedValueResolver != null) {
    26. initialDelayString = this.embeddedValueResolver.resolveStringValue(initialDelayString);
    27. }
    28. try {
    29. initialDelay = (long)Integer.parseInt(initialDelayString);
    30. } catch (NumberFormatException var20) {
    31. throw new IllegalArgumentException("Invalid initialDelayString value \"" + initialDelayString + "\" - cannot parse into integer");
    32. }
    33. }
    34. // Check cron expression
    35. String cron = scheduled.cron();
    36. if (StringUtils.hasText(cron)) {
    37. Assert.isTrue(initialDelay == -1L, "'initialDelay' not supported for cron triggers");
    38. processedSchedule = true;
    39. String zone = scheduled.zone();
    40. if (this.embeddedValueResolver != null) {
    41. cron = this.embeddedValueResolver.resolveStringValue(cron);
    42. zone = this.embeddedValueResolver.resolveStringValue(zone);
    43. }
    44. TimeZone timeZone;
    45. if (StringUtils.hasText(zone)) {
    46. timeZone = StringUtils.parseTimeZoneString(zone);
    47. } else {
    48. timeZone = TimeZone.getDefault();
    49. }
    50. //放入cron任务列表中(不执行)
    51. this.registrar.addCronTask(new CronTask(runnable, new CronTrigger(cron, timeZone)));
    52. }
    53. if (initialDelay < 0L) {
    54. initialDelay = 0L;
    55. }
    56. // Check fixed delay
    57. long fixedDelay = scheduled.fixedDelay();
    58. if (fixedDelay >= 0L) {
    59. Assert.isTrue(!processedSchedule, errorMessage);
    60. processedSchedule = true;
    61. this.registrar.addFixedDelayTask(new IntervalTask(runnable, fixedDelay, initialDelay));
    62. }
    63. String fixedDelayString = scheduled.fixedDelayString();
    64. if (StringUtils.hasText(fixedDelayString)) {
    65. Assert.isTrue(!processedSchedule, errorMessage);
    66. processedSchedule = true;
    67. if (this.embeddedValueResolver != null) {
    68. fixedDelayString = this.embeddedValueResolver.resolveStringValue(fixedDelayString);
    69. }
    70. try {
    71. fixedDelay = (long)Integer.parseInt(fixedDelayString);
    72. } catch (NumberFormatException var19) {
    73. throw new IllegalArgumentException("Invalid fixedDelayString value \"" + fixedDelayString + "\" - cannot parse into integer");
    74. }
    75. this.registrar.addFixedDelayTask(new IntervalTask(runnable, fixedDelay, initialDelay));
    76. }
    77. //执行频率类型(long类型)
    78. long fixedRate = scheduled.fixedRate();
    79. if (fixedRate >= 0L) {
    80. Assert.isTrue(!processedSchedule, errorMessage);
    81. processedSchedule = true;
    82. this.registrar.addFixedRateTask(new IntervalTask(runnable, fixedRate, initialDelay));
    83. }
    84. //执行频率类型(字符串类型,不接收参数计算如:600*20)
    85. String fixedRateString = scheduled.fixedRateString();
    86. if (StringUtils.hasText(fixedRateString)) {
    87. Assert.isTrue(!processedSchedule, errorMessage);
    88. processedSchedule = true;
    89. if (this.embeddedValueResolver != null) {
    90. fixedRateString = this.embeddedValueResolver.resolveStringValue(fixedRateString);
    91. }
    92. try {
    93. fixedRate = (long)Integer.parseInt(fixedRateString);
    94. } catch (NumberFormatException var18) {
    95. throw new IllegalArgumentException("Invalid fixedRateString value \"" + fixedRateString + "\" - cannot parse into integer");
    96. }
    97. //放入FixedRate任务列表中(不执行)
    98. this.registrar.addFixedRateTask(new IntervalTask(runnable, fixedRate, initialDelay));
    99. }
    100. Assert.isTrue(processedSchedule, errorMessage);
    101. } catch (IllegalArgumentException var23) {
    102. throw new IllegalStateException("Encountered invalid @Scheduled method '" + method.getName() + "': " + var23.getMessage());
    103. }
    104. }
    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);
            }
    
    }