ScheduledAnnotationBeanPostProcessor is responsible for detecting @Scheduled methods and registering them with a TaskScheduler. This BeanPostProcessor is automatically registered when we use @EnableScheduling on Spring's configuration class.
Following example shows how we can customize the behavior of ScheduledAnnotationBeanPostProcessor. We are going to do that by extending it.
Example
The Processor
This extension of ScheduledAnnotationBeanPostProcessor just do some logging, but it can be used for customization like dynamic scheduling based on runtime conditions, environment-specific scheduling, performance monitoring, conditionally enable or disable tasks etc.
package com.logicbig.example;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor;
import java.lang.reflect.Method;
public class CustomScheduledBeanPostProcessor extends ScheduledAnnotationBeanPostProcessor {
@Override
protected Runnable createRunnable(Object target, Method method, String qualifier) {
//do some customizing if required
Runnable runnable = super.createRunnable(target, method, qualifier);
return () -> {
System.out.printf("Running method %s.%s%n",
target.getClass().getSimpleName(), method.getName());
runnable.run();
System.out.printf("Finished running method %s.%s%n",
target.getClass().getSimpleName(), method.getName());
System.out.println("-------");
};
}
@Override
protected void processScheduled(Scheduled scheduled, Method method, Object bean) {
System.out.printf("Processing @Scheduled method: %s.%s, scheduled Type: %s%n",
method.getDeclaringClass().getSimpleName(), method.getName(), scheduled);
super.processScheduled(scheduled, method, bean);
}
}
The bean using @Scheduled annotations
package com.logicbig.example;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalTime;
@Component
public class MyBean {
@Scheduled(fixedDelay = 1000)
public void runTask() {
System.out.printf("task thread: %s, time: %s%n",
Thread.currentThread().getName(),
LocalTime.now());
}
@Scheduled(fixedRate = 2000)
public void runTask2() {
System.out.printf("task 2 thread: %s, time: %s%n",
Thread.currentThread().getName(),
LocalTime.now());
}
}
Main class
package com.logicbig.example;
import org.springframework.context.annotation.*;
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableScheduling
@ComponentScan
@Configuration
public class ScheduledCustomizedProcessorExample {
@Bean
@Primary
public static CustomScheduledBeanPostProcessor customScheduledBeanPostProcessor() {
return new CustomScheduledBeanPostProcessor();
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(
ScheduledCustomizedProcessorExample.class);
}
}
OutputProcessing @Scheduled method: MyBean.runTask2, scheduled Type: @org.springframework.scheduling.annotation.Scheduled(scheduler="", cron="", fixedRateString="", zone="", fixedDelay=-1L, fixedRate=2000L, initialDelayString="", initialDelay=-1L, timeUnit=MILLISECONDS, fixedDelayString="") Processing @Scheduled method: MyBean.runTask, scheduled Type: @org.springframework.scheduling.annotation.Scheduled(scheduler="", cron="", fixedRateString="", zone="", fixedDelay=1000L, fixedRate=-1L, initialDelayString="", initialDelay=-1L, timeUnit=MILLISECONDS, fixedDelayString="") Running method MyBean.runTask2 task 2 thread: pool-2-thread-1, time: 13:58:05.597719300 Finished running method MyBean.runTask2 ------- Running method MyBean.runTask task thread: pool-2-thread-1, time: 13:58:05.599712400 Finished running method MyBean.runTask ------- task 2 thread: pool-1-thread-1, time: 13:58:05.608682600 task thread: pool-1-thread-1, time: 13:58:05.609678900 Running method MyBean.runTask task thread: pool-2-thread-1, time: 13:58:06.602690300 Finished running method MyBean.runTask ------- task thread: pool-1-thread-1, time: 13:58:06.610445 task 2 thread: pool-1-thread-1, time: 13:58:07.531037300 Running method MyBean.runTask2 task 2 thread: pool-2-thread-1, time: 13:58:07.533085600 Finished running method MyBean.runTask2 ------- Running method MyBean.runTask task thread: pool-2-thread-1, time: 13:58:07.603913900 Finished running method MyBean.runTask ------- task thread: pool-1-thread-1, time: 13:58:07.611711700 Running method MyBean.runTask task thread: pool-1-thread-1, time: 13:58:08.619743700 task thread: pool-2-thread-1, time: 13:58:08.619743700 Finished running method MyBean.runTask ------- Running method MyBean.runTask2 task 2 thread: pool-1-thread-1, time: 13:58:09.539502 task 2 thread: pool-2-thread-1, time: 13:58:09.539502 Finished running method MyBean.runTask2 ------- Running method MyBean.runTask task thread: pool-1-thread-1, time: 13:58:09.633156400 task thread: pool-2-thread-1, time: 13:58:09.633156400 Finished running method MyBean.runTask ------- .....................
Example ProjectDependencies and Technologies Used: - spring-context 6.2.12 (Spring Context)
Version Compatibility: 6.1.0 - 6.2.12 Version compatibilities of spring-context with this example:
- 6.1.0
- 6.1.1
- 6.1.2
- 6.1.3
- 6.1.4
- 6.1.5
- 6.1.6
- 6.1.7
- 6.1.8
- 6.1.9
- 6.1.10
- 6.1.11
- 6.1.12
- 6.1.13
- 6.1.14
- 6.1.15
- 6.1.16
- 6.1.17
- 6.1.18
- 6.1.19
- 6.1.20
- 6.1.21
- 6.2.0
- 6.2.1
- 6.2.2
- 6.2.3
- 6.2.4
- 6.2.5
- 6.2.6
- 6.2.7
- 6.2.8
- 6.2.9
- 6.2.10
- 6.2.11
- 6.2.12
Versions in green have been tested.
- JDK 25
- Maven 3.9.11
|
|