本文主要研究下springboot2的ScheduledTasksEndpointhtml
@Component public class ScheduleTask { @Scheduled(cron = "0 0 5 * * ?") public void cronJob(){ } @Scheduled(fixedDelay = 2*60*1000,initialDelay = 30*1000) public void fixedDelayJob(){ } @Scheduled(fixedRate = 5 * 1000) public void fixedRatejob(){ } }
@Configuration public class ScheduleConfig implements SchedulingConfigurer { @Override public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { taskRegistrar.addCronTask(new Runnable() { @Override public void run() { System.out.println("hello"); } },"0 0 6 * * ?"); } }
{ "cron": [ { "runnable": { "target": "com.example.task.ScheduleTask.cronJob" }, "expression": "0 0 5 * * ?" }, { "runnable": { "target": "com.example.config.ScheduleConfig$1" }, "expression": "0 0 6 * * ?" } ], "fixedDelay": [ { "runnable": { "target": "com.example.task.ScheduleTask.fixedDelayJob" }, "initialDelay": 30000, "interval": 120000 } ], "fixedRate": [ { "runnable": { "target": "com.example.task.ScheduleTask.fixedRatejob" }, "initialDelay": 0, "interval": 5000 } ] }
這裏分了三種類型來展現,一個是cron表達式類型,一個是fixedDelay類型,一個是fixedRate類型。
spring-boot-actuator-autoconfigure-2.0.0.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/scheduling/ScheduledTasksEndpointAutoConfiguration.javajava
/** * {@link EnableAutoConfiguration Auto-configuration} for {@link ScheduledTasksEndpoint}. * * @author Andy Wilkinson * @since 2.0.0 */ @Configuration public class ScheduledTasksEndpointAutoConfiguration { @Bean @ConditionalOnMissingBean @ConditionalOnEnabledEndpoint public ScheduledTasksEndpoint scheduledTasksEndpoint( ObjectProvider<List<ScheduledTaskHolder>> holders) { return new ScheduledTasksEndpoint(holders.getIfAvailable(Collections::emptyList)); } }
能夠看到從2.0開始有這個config,這裏主要建立了一個ScheduledTasksEndpoint,同時在構造器傳入ObjectProvider<List<ScheduledTaskHolder>> holders
spring-boot-actuator-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/scheduling/ScheduledTasksEndpoint.javaspring
/** * {@link Endpoint} to expose information about an application's scheduled tasks. * * @author Andy Wilkinson * @since 2.0.0 */ @Endpoint(id = "scheduledtasks") public class ScheduledTasksEndpoint { private final Collection<ScheduledTaskHolder> scheduledTaskHolders; public ScheduledTasksEndpoint(Collection<ScheduledTaskHolder> scheduledTaskHolders) { this.scheduledTaskHolders = scheduledTaskHolders; } @ReadOperation public ScheduledTasksReport scheduledTasks() { Map<TaskType, List<TaskDescription>> descriptionsByType = this.scheduledTaskHolders .stream().flatMap((holder) -> holder.getScheduledTasks().stream()) .map(ScheduledTask::getTask).map(TaskDescription::of) .filter(Objects::nonNull) .collect(Collectors.groupingBy(TaskDescription::getType)); return new ScheduledTasksReport(descriptionsByType); } //...... }
這裏主要根據scheduledTaskHolders建立ScheduledTasksReport
spring-boot-actuator-2.0.0.RELEASE-sources.jar!/org/springframework/boot/actuate/scheduling/ScheduledTasksEndpoint.javaexpress
/** * A report of an application's scheduled {@link Task Tasks}, primarily intended for * serialization to JSON. */ public static final class ScheduledTasksReport { private final List<TaskDescription> cron; private final List<TaskDescription> fixedDelay; private final List<TaskDescription> fixedRate; private ScheduledTasksReport( Map<TaskType, List<TaskDescription>> descriptionsByType) { this.cron = descriptionsByType.getOrDefault(TaskType.CRON, Collections.emptyList()); this.fixedDelay = descriptionsByType.getOrDefault(TaskType.FIXED_DELAY, Collections.emptyList()); this.fixedRate = descriptionsByType.getOrDefault(TaskType.FIXED_RATE, Collections.emptyList()); } public List<TaskDescription> getCron() { return this.cron; } public List<TaskDescription> getFixedDelay() { return this.fixedDelay; } public List<TaskDescription> getFixedRate() { return this.fixedRate; } }
這裏能夠看到report將定時任務歸爲cron、fixedDelay、fixedRate三類。
spring-context-5.0.5.RELEASE-sources.jar!/org/springframework/scheduling/annotation/SchedulingConfiguration.javaspringboot
/** * {@code @Configuration} class that registers a {@link ScheduledAnnotationBeanPostProcessor} * bean capable of processing Spring's @{@link Scheduled} annotation. * * <p>This configuration class is automatically imported when using the * {@link EnableScheduling @EnableScheduling} annotation. See * {@code @EnableScheduling}'s javadoc for complete usage details. * * @author Chris Beams * @since 3.1 * @see EnableScheduling * @see ScheduledAnnotationBeanPostProcessor */ @Configuration @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class SchedulingConfiguration { @Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME) @Role(BeanDefinition.ROLE_INFRASTRUCTURE) public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() { return new ScheduledAnnotationBeanPostProcessor(); } }
EnableScheduling會啓動這個配置,而後建立ScheduledAnnotationBeanPostProcessor
spring-context-5.0.5.RELEASE-sources.jar!/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.javaapp
/** * Bean post-processor that registers methods annotated with @{@link Scheduled} * to be invoked by a {@link org.springframework.scheduling.TaskScheduler} according * to the "fixedRate", "fixedDelay", or "cron" expression provided via the annotation. * * <p>This post-processor is automatically registered by Spring's * {@code <task:annotation-driven>} XML element, and also by the * {@link EnableScheduling @EnableScheduling} annotation. * * <p>Autodetects any {@link SchedulingConfigurer} instances in the container, * allowing for customization of the scheduler to be used or for fine-grained * control over task registration (e.g. registration of {@link Trigger} tasks. * See the @{@link EnableScheduling} javadocs for complete usage details. * * @author Mark Fisher * @author Juergen Hoeller * @author Chris Beams * @author Elizabeth Chatman * @since 3.0 * @see Scheduled * @see EnableScheduling * @see SchedulingConfigurer * @see org.springframework.scheduling.TaskScheduler * @see org.springframework.scheduling.config.ScheduledTaskRegistrar * @see AsyncAnnotationBeanPostProcessor */ public class ScheduledAnnotationBeanPostProcessor implements ScheduledTaskHolder, MergedBeanDefinitionPostProcessor, DestructionAwareBeanPostProcessor, Ordered, EmbeddedValueResolverAware, BeanNameAware, BeanFactoryAware, ApplicationContextAware, SmartInitializingSingleton, ApplicationListener<ContextRefreshedEvent>, DisposableBean { private final ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar(); private final Map<Object, Set<ScheduledTask>> scheduledTasks = new IdentityHashMap<Object, Set<ScheduledTask>>(16); /** * Return all currently scheduled tasks, from {@link Scheduled} methods * as well as from programmatic {@link SchedulingConfigurer} interaction. * @since 5.0.2 */ @Override public Set<ScheduledTask> getScheduledTasks() { Set<ScheduledTask> result = new LinkedHashSet<>(); synchronized (this.scheduledTasks) { Collection<Set<ScheduledTask>> allTasks = this.scheduledTasks.values(); for (Set<ScheduledTask> tasks : allTasks) { result.addAll(tasks); } } result.addAll(this.registrar.getScheduledTasks()); return result; } @Override public Object postProcessAfterInitialization(final Object bean, String beanName) { Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean); if (!this.nonAnnotatedClasses.contains(targetClass)) { Map<Method, Set<Scheduled>> annotatedMethods = MethodIntrospector.selectMethods(targetClass, (MethodIntrospector.MetadataLookup<Set<Scheduled>>) method -> { Set<Scheduled> scheduledMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations( method, Scheduled.class, Schedules.class); return (!scheduledMethods.isEmpty() ? scheduledMethods : null); }); if (annotatedMethods.isEmpty()) { this.nonAnnotatedClasses.add(targetClass); if (logger.isTraceEnabled()) { logger.trace("No @Scheduled annotations found on bean class: " + bean.getClass()); } } else { // Non-empty set of methods annotatedMethods.forEach((method, scheduledMethods) -> scheduledMethods.forEach(scheduled -> processScheduled(scheduled, method, bean))); if (logger.isDebugEnabled()) { logger.debug(annotatedMethods.size() + " @Scheduled methods processed on bean '" + beanName + "': " + annotatedMethods); } } } return bean; } @Override public void afterSingletonsInstantiated() { // Remove resolved singleton classes from cache this.nonAnnotatedClasses.clear(); if (this.applicationContext == null) { // Not running in an ApplicationContext -> register tasks early... finishRegistration(); } } @Override public void onApplicationEvent(ContextRefreshedEvent event) { if (event.getApplicationContext() == this.applicationContext) { // Running in an ApplicationContext -> register tasks this late... // giving other ContextRefreshedEvent listeners a chance to perform // their work at the same time (e.g. Spring Batch's job registration). finishRegistration(); } } //...... }
protected void processScheduled(Scheduled scheduled, Method method, Object bean) { //... 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))); //... synchronized (this.scheduledTasks) { Set<ScheduledTask> registeredTasks = this.scheduledTasks.get(bean); if (registeredTasks == null) { registeredTasks = new LinkedHashSet<>(4); this.scheduledTasks.put(bean, registeredTasks); } registeredTasks.addAll(tasks); } }
這裏將註解的定時任務經過registrar去註冊和調度,同時也將這些定時任務添加到registeredTasks中(這裏的scheduledTasks類型爲Map<Object, Set<ScheduledTask>> ,registeredTasks是這個map的value)
自springboot2.0起,在actuator中新提供了ScheduledTasksEndpoint,默承認以經過/actuator/scheduledtasks來訪問當前應用的定時任務信息,很是便利。ide