During the project development process, if it is some simple engineering or non-distributed engineering, we can generally use the @EnableScheduling annotation and the @Scheduled annotation to implement simple timing tasks, or we can use the SchedulingConfigurer interface to implement timing tasks. So how to dynamically generate timing tasks?
The following are specific steps. You can combine the database to store parameter data required for timing tasks, such as the name of the bean, method name, method parameters, executed expressions, etc.
1. Configure the thread pool required for timing tasks
import ; import ; import ; import ; // Configure the timed task thread pool@Configuration public class SchedulingConfig { @Bean public TaskScheduler taskScheduler() { ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); // Number of core threads for the timed task execution thread pool (4); (true); ("TaskSchedulerThreadPool-test-"); return taskScheduler; } }
2. Create a package class for ScheduledFuture
//ScheduledFuture's packaging classpublic final class ScheduledTask { volatile ScheduledFuture<?> future; /** * Cancel the scheduled task */ public void cancel() { ScheduledFuture<?> future = ; if (future != null) { (true); } } }
3. Register timed tasks, add and delete tasks
/** * Add timed task registration to add and delete timed tasks. */ @Component public class CronTaskRegistrar implements DisposableBean { private final Map<Runnable, ScheduledTask> scheduledTasks = new ConcurrentHashMap<>(16); @Autowired private TaskScheduler taskScheduler; public TaskScheduler getScheduler() { return ; } // Add timed tasks public void addCronTask(Runnable task, String cronExpression) { addCronTask(new CronTask(task, cronExpression)); } // Add timed tasks public void addCronTask(CronTask cronTask) { if (cronTask != null) { Runnable task = (); if ((task)) { removeCronTask(task); } (task, scheduleCronTask(cronTask)); } } // Remove timing tasks public void removeCronTask(Runnable task) { ScheduledTask scheduledTask = (task); if (scheduledTask != null) (); } public ScheduledTask scheduleCronTask(CronTask cronTask) { ScheduledTask scheduledTask = new ScheduledTask(); = ((), ()); return scheduledTask; } @Override public void destroy() { for (ScheduledTask task : ()) { (); } (); } }
4. Create a class that executes the method in the bean
// Add the Runnable interface implementation class, which is called by the timed task thread pool, and is used to execute the methods in the specified bean.@Slf4j public class SchedulingRunnable implements Runnable { // bean name private String beanName; // Method name private String methodName; // Method parameters private String params; public SchedulingRunnable(String beanName, String methodName) { this(beanName, methodName, null); } public SchedulingRunnable(String beanName, String methodName, String params) { = beanName; = methodName; = params; } @Override public void run() { ("Timed tasks start execution - bean:{},method:{},parameter:{}", beanName, methodName, params); long startTime = (); try { Object target = (beanName); Method method = null; if ((params)) { method = ().getDeclaredMethod(methodName, ); } else { method = ().getDeclaredMethod(methodName); } (method); if ((params)) { (target, params); } else { (target); } } catch (Exception ex) { (("Timed task execution exception - bean: %s, method: %s, parameter: %s ", beanName, methodName, params), ex); } long times = () - startTime; ("Timed task execution ends - bean:{},method:{},parameter:{},time consuming:{} millisecond", beanName, methodName, params, times); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != ()) return false; SchedulingRunnable that = (SchedulingRunnable) o; if (params == null) { return () && () && == null; } return () && () && (); } @Override public int hashCode() { if (params == null) { return (beanName, methodName); } return (beanName, methodName, params); } }
5. Get bean from spring container
// Get bean from spring container@Component public class SpringContextUtils implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { = applicationContext; } public static Object getBean(String name) { return (name); } public static <T> T getBean(Class<T> requiredType) { return (requiredType); } public static <T> T getBean(String name, Class<T> requiredType) { return (name, requiredType); } public static boolean containsBean(String name) { return (name); } public static boolean isSingleton(String name) { return (name); } public static Class<? extends Object> getType(String name) { return (name); } }
6. Create specific execution beans and methods
// Test class@Component("testTask") public class TestTask { /** * There are ginseng methods * @param params */ public void taskWithParams(String params) { ("Execute sample task with parameters:" + params); } /** * No misery method */ public void taskNoParams() { ("Execute sample task without parameters"); } }
7. Interface testing class
@RestController @RequestMapping("/test") public class TestController { @Autowired private CronTaskRegistrar cronTaskRegistrar; @RequestMapping("/addTest") public String addTest(boolean flg){ SchedulingRunnable task; if (flg) { // Create a miserable task task = new SchedulingRunnable("testTask", "taskNoParams"); } else { task = new SchedulingRunnable("testTask", "taskWithParams", "hello word"); } (task, "0/1 * * * * *"); return "ok"; } @RequestMapping("/updateTest") public String updateTest(boolean flg){ //Remove first and then add if(flg) { // Create a miserable task SchedulingRunnable task = new SchedulingRunnable("testTask", "taskNoParams"); (task); } else { SchedulingRunnable task = new SchedulingRunnable("testTask", "taskWithParams", "hello word"); (task); } SchedulingRunnable task = new SchedulingRunnable("testTask", "taskWithParams", "hello word"); (task, "0/5 * * * * *"); return "ok"; } @RequestMapping("/delTest") public String delTest(){ SchedulingRunnable task = new SchedulingRunnable("testTask", "taskNoParams"); (task); return "ok"; } @RequestMapping("/startTest") public String startTest(boolean flg){ /** * The logic of the start-stop task is to create a new task or delete a task, and the parameters are consistent. * You can combine the database to store configuration information into the database */ if(flg) { SchedulingRunnable task = new SchedulingRunnable("testTask", "taskNoParams"); (task, "0/5 * * * * *"); } else { SchedulingRunnable task = new SchedulingRunnable("testTask", "taskNoParams"); (task); } return "ok"; } }
8. Combining the database, create the corresponding entity
// Timed task entity@Data public class JobEntity { /** * Task ID */ private Integer jobId; /** * bean name */ private String beanName; /** * Method name */ private String methodName; /** * Method parameters */ private String methodParams; /** * cron expression */ private String cronExpression; /** * Status (1 Normal, 0 Pause) */ private Integer jobStatus; /** * Remark */ private String remark; /** * Creation time */ private Date createTime; /** * Update time */ private Date updateTime; }
9. Read the tasks to be performed by the database
When the program starts, read the database and create tasks to be executed
/** * @description: Initialize the database task, and you can load the tasks in the database when the process starts again. * @author: HK * @since: 2025/4/21 18:21 */ @Component @Slf4j public class InitTask implements CommandLineRunner { @Autowired private CronTaskRegistrar cronTaskRegistrar; @Override public void run(String... args) { // Initial loading of the database with normal status/* List<SysJobPO> jobList = ("1"); if ((jobList)) { for (SysJobPO job : jobList) { SchedulingRunnable task = new SchedulingRunnable((), (), ()); (task, ()); } ("The timing task has been loaded..."); }*/ } }
Summarize
The above is personal experience. I hope you can give you a reference and I hope you can support me more.