博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
聊聊springboot2的ScheduledTasksEndpoint
阅读量:5948 次
发布时间:2019-06-19

本文共 10820 字,大约阅读时间需要 36 分钟。

  hot3.png

本文主要研究下springboot2的ScheduledTasksEndpoint

实例

注解形式

@Componentpublic 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(){    }}

动态添加

@Configurationpublic 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 * * ?");    }}

/actuator/scheduledtasks

{  "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类型。

源码解析

ScheduledTasksEndpointAutoConfiguration

spring-boot-actuator-autoconfigure-2.0.0.RELEASE-sources.jar!/org/springframework/boot/actuate/autoconfigure/scheduling/ScheduledTasksEndpointAutoConfiguration.java

/** * {@link EnableAutoConfiguration Auto-configuration} for {@link ScheduledTasksEndpoint}. * * @author Andy Wilkinson * @since 2.0.0 */@Configurationpublic class ScheduledTasksEndpointAutoConfiguration {	@Bean	@ConditionalOnMissingBean	@ConditionalOnEnabledEndpoint	public ScheduledTasksEndpoint scheduledTasksEndpoint(			ObjectProvider
> holders) { return new ScheduledTasksEndpoint(holders.getIfAvailable(Collections::emptyList)); }}

可以看到从2.0开始有这个config,这里主要创建了一个ScheduledTasksEndpoint,同时在构造器传入ObjectProvider<List<ScheduledTaskHolder>> holders

ScheduledTasksEndpoint

spring-boot-actuator-2.0.1.RELEASE-sources.jar!/org/springframework/boot/actuate/scheduling/ScheduledTasksEndpoint.java

/** * {@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
scheduledTaskHolders; public ScheduledTasksEndpoint(Collection
scheduledTaskHolders) { this.scheduledTaskHolders = scheduledTaskHolders; } @ReadOperation public ScheduledTasksReport scheduledTasks() { Map
> 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

ScheduledTasksReport

spring-boot-actuator-2.0.0.RELEASE-sources.jar!/org/springframework/boot/actuate/scheduling/ScheduledTasksEndpoint.java

/**	 * A report of an application's scheduled {@link Task Tasks}, primarily intended for	 * serialization to JSON.	 */	public static final class ScheduledTasksReport {		private final List
cron; private final List
fixedDelay; private final List
fixedRate; private ScheduledTasksReport( Map
> 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
getCron() { return this.cron; } public List
getFixedDelay() { return this.fixedDelay; } public List
getFixedRate() { return this.fixedRate; } }

这里可以看到report将定时任务归为cron、fixedDelay、fixedRate三类。

SchedulingConfiguration

spring-context-5.0.5.RELEASE-sources.jar!/org/springframework/scheduling/annotation/SchedulingConfiguration.java

/** * {@code @Configuration} class that registers a {@link ScheduledAnnotationBeanPostProcessor} * bean capable of processing Spring's @{@link Scheduled} annotation. * * 

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

ScheduledAnnotationBeanPostProcessor

spring-context-5.0.5.RELEASE-sources.jar!/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.java

/** * 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. * * 

This post-processor is automatically registered by Spring's * {@code

} XML element, and also by the * {@link EnableScheduling @EnableScheduling} annotation. * *

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

, DisposableBean { private final ScheduledTaskRegistrar registrar = new ScheduledTaskRegistrar(); private final Map
> scheduledTasks = new IdentityHashMap
>(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
getScheduledTasks() { Set
result = new LinkedHashSet<>(); synchronized (this.scheduledTasks) { Collection
> allTasks = this.scheduledTasks.values(); for (Set
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
> annotatedMethods = MethodIntrospector.selectMethods(targetClass, (MethodIntrospector.MetadataLookup
>) method -> { Set
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(); } } //......}

  • getScheduledTasks实现的是ScheduledTaskHolder的接口,用于获取注册的定时任务,它先添加Map<Object, Set<ScheduledTask>> scheduledTasks的values,然后再合并registrar.getScheduledTasks()。这里之所以要合并,主要是系统可能通过ScheduledTaskRegistrar在运行时动态添加/更新/覆盖定时任务

  • 这里postProcessAfterInitialization会去寻找@Scheduled的方法,然后调用processScheduled去注册

  • onApplicationEvent以及afterSingletonsInstantiated会触发finishRegistration,这个方法主要是从实现SchedulingConfigurer接口的方法里头获取动态配置的定时任务信息,即将这里new的一个ScheduledTaskRegistrar传递给SchedulingConfigurer实现类的接口,然后定时任务信息都统一添加到一个ScheduledTaskRegistrar中。

processScheduled

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
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来访问当前应用的定时任务信息,非常便利。

doc

转载于:https://my.oschina.net/go4it/blog/1798168

你可能感兴趣的文章
平衡二叉树
查看>>
centos7 中 systemd systemctl管理服务的命令
查看>>
企业级办公室iptables防火墙应用案例
查看>>
Ubuntu python 安装使用sqlalchemy
查看>>
HAProxy 之 ACL介绍和使用
查看>>
OEL 6.4中安装Oracle 11g_R2_64bit
查看>>
vSphere 5 中的多网卡 vMotion
查看>>
Python实例:向量基本操作
查看>>
7月第一周.COM增近8万 ×××域名.XXX仅增14个
查看>>
12月第3周在线视频网站覆盖数排名TOP15:优酷夺冠
查看>>
全球域名注册商(国际域名)保有量及市场份额(6月6日)
查看>>
Linux常用的命令和脚本
查看>>
Linux curl命令参数详解
查看>>
Asterisk的MusicOnHold设置(1.8)
查看>>
LightBus新浪微博客户端开源下载
查看>>
交换机时间同步
查看>>
土豆网发布互动娱乐急播平台Channel豆
查看>>
在 Ali Kubernetes 系统中,我们这样实践混沌工程
查看>>
Linux-rsync+inotify 文件实时同步
查看>>
七Python异常和文件处理(二)
查看>>