参考:
@Target(TYPE)
@Retention(RUNTIME)
@Import(SchedulingConfiguration.class)
@Documented
public @interface EnableScheduling
【1】@EnableScheduling与@Scheduled注解的使用及作用
启用spring的调度任务执行功能,类似于spring的 <task:*> xml命名空间提供的功能。应按照以下方式用于@Configuration类。
【1.1】@EnableScheduling的使用
@Configuration
@EnableScheduling
public class AppConfig {
// various @Bean definitions
}
这样就可以检测容器中任何被spring管理的bean上的@Scheduled注解。
例,给定类MyTask:
package com.myco.tasks;
public class MyTask {
@Scheduled(fixedRate=1000)
public void work() {
// task execution logic
}
}
以下配置会确保MyTask.work()方法没1000ms被调用一次;
@Configuration
@EnableScheduling
public class AppConfig {
@Bean
public MyTask task() {
return new MyTask();
}
}
或者,如果MyTask被@Component标注,以下配置会确保它的@Scheduled方法在期望的间隔时间被调用;
@Configuration
@EnableScheduling
@ComponentScan(basePackages="com.myco.tasks")
public class AppConfig {
}
【1.2】在@Configuration类中同时使用@EnableScheduling与 @Scheduled注解
被@Scheduled标注的方法甚至直接在 @Configuration类中声明,因为@Configuration类也是被spring管理的bean;
@Configuration
@EnableScheduling
public class AppConfig {
@Scheduled(fixedRate=1000)
public void work() {
// task execution logic
}
【2】任务调度器
默认情况下,spring将会查找关联的调度器定义; 要么是容器中唯一的TaskScheduler bean,要么是命名为taskScheduler类型为TaskScheduler的bean,同样的查找方法也会针对 ScheduledExecutorService bean。
如果两者均无法解析(两个类的bean都没有查找到),则spring会默认在注册器中创建并使用单线程调度器。
【2.1】@Configuration类按需实现SchedulingConfigurer(调度配置器)
当需要更多控制时,@Configuration类可以实现 SchedulingConfigurer。这会允许访问隐含的ScheduledTaskRegistrar实例。
【例】下面例子演示如何定义执行器用于执行调度任务;
@Configuration
@EnableScheduling
public class AppConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
}
@Bean(destroyMethod="shutdown")
public Executor taskExecutor() {
return Executors.newScheduledThreadPool(100);
}
}
【注意】
以上例子中,使用了@Bean(destroyMethod="shutdown")。这样可以确保任务执行器在spring应用上下文关闭时能够被正确关闭。
实现SchedulingConfigurer也允许通过ScheduledRegistrar对任务注册进行精细化控制。
【例】以下代码根据自定义触发器实现,执行特定bean方法;
@Configuration
@EnableScheduling
public class AppConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskScheduler());
taskRegistrar.addTriggerTask(
() -> myTask().work(),
new CustomTrigger()
);
}
@Bean(destroyMethod="shutdown")
public Executor taskScheduler() {
return Executors.newScheduledThreadPool(42);
}
@Bean
public MyTask myTask() {
return new MyTask();
}
}
【2.2】使用xml定义调度器及调度任务
作为参考,上面例子可以与下面的xml配置做比较。
<beans>
<task:annotation-driven scheduler="taskScheduler"/>
<task:scheduler id="taskScheduler" pool-size="42"/>
<task:scheduled-tasks scheduler="taskScheduler">
<task:scheduled ref="myTask" method="work" fixed-rate="1000"/>
</task:scheduled-tasks>
<bean id="myTask" class="com.foo.MyTask"/>
</beans>
这些示例是等效的,只是在 XML 中使用了固定利率周期而不是自定义触发器实现;这是因为 task: namespace scheduling 无法轻松公开此类支持。这只是一个演示,展示了基于代码的方法如何通过直接访问实际组件来实现最大程度的可配置性。
【3】注意
注意:@EnableScheduling 仅适用于其本地应用程序上下文,允许在不同级别选择性地调度 bean。如果您需要在多个级别应用其行为,请在每个单独的上下文中重新声明 @EnableScheduling,例如,公共根 Web 应用程序上下文和任何单独的 DispatcherServlet 应用程序上下文。