使用SpringBoot实现动态增删启停定时任务
简介
- 在spring boot项目中,可以通过@EnableScheduling注解和@Scheduled注解实现定时任务,也可以通过SchedulingConfigurer接口来实现定时任务。但是这两种方式不能动态添加、删除、启动、停止任务。
- 要实现动态增删启停定时任务功能,比较广泛的做法是集成Quartz框架。但是本人的开发原则是:在满足项目需求的情况下,尽量少的依赖其它框架,避免项目过于臃肿和复杂。
- 查看spring-context这个jar包中org.springframework.scheduling.ScheduledTaskRegistrar这个类的源代码,发现可以通过改造这个类就能实现动态增删启停定时任务功能。

一、实现SpringBoot动态增删启停定时任务
1. 添加执行定时任务的线程池配置类
@Configuration
public class SchedulingConfig {
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(4);
taskScheduler.setRemoveOnCancelPolicy(true);
taskScheduler.setThreadNamePrefix("TaskSchedulerThreadPool-");
return taskScheduler;
}
}
2. 添加ScheduledFuture的包装类。ScheduledFuture是ScheduledExecutorService定时任务线程池的执行结果
public final class ScheduledTask {
volatile ScheduledFuture<?> future;
public void cancel() {
ScheduledFuture<?> future = this.future;
if (future != null) {
future.cancel(true);
}
}
}
3. 添加Runnable接口实现类,被定时任务线程池调用,用来执行指定bean里面的
public class SchedulingRunnable implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(SchedulingRunnable.class);
private String beanName;
private String methodName;
private String params;
public SchedulingRunnable(String beanName, String methodName) {
this(beanName, methodName, null);
}
public SchedulingRunnable(String beanName, String methodName, String params) {
this.beanName = beanName;
this.methodName = methodName;
this.params = params;
}
@Override
public void run() {
logger.info("定时任务开始执行 - bean:{},方法:{},参数:{}", beanName, methodName, params);
long startTime = System.currentTimeMillis();
try {
Object target = SpringContextUtils.getBean(beanName);
Method method = null;
if (StringUtils.isNotEmpty(params)) {
method = target.getClass().getDeclaredMethod(methodName, String.class);
} else {
method = target.getClass().getDeclaredMethod(methodName);
}
ReflectionUtils.makeAccessible(method);
if (StringUtils.isNotEmpty(params)) {
method.invoke(target, params);
} else {
method.