Maybe I have some outdated knowledge but it is the same as described here https://stackoverflow.com/a/2657465/2674303
But now I noticed that this example works without any exceptions:
@Service
@EnableScheduling
public final class MyService {
@PostConstruct
public void init(){
System.out.println("MyService started");
}
@Scheduled(fixedDelay= 1000)
public void scheduleCall() {
System.out.println("scheduleCall");
}
}
Could you pease provide how does it work ?
@Scheduled annotation does not require proxy creation. The mechanism is different. After bean initialization Spring called post-processor ScheduledAnnotationBeanPostProcessor. Post processor searches for all methods annotated with @Scheduled
and registers them to TaskScheduller for execution. Method execution will be performed via reflection.
See ScheduledAnnotationBeanPostProcessor source code.
Processing of @Scheduled annotations is performed by registering a ScheduledAnnotationBeanPostProcessor. This can be done manually or, more conveniently, through the task:annotation-driven/ XML element or @EnableScheduling annotation.
ScheduledAnnotationBeanPostProcessor
Bean post-processor that registers methods annotated with @Scheduled to be invoked by a TaskScheduler according to the "fixedRate", "fixedDelay", or "cron" expression provided via the annotation. This post-processor is automatically registered by Spring's task:annotation-driven XML element, and also by the @EnableScheduling annotation.
Autodetects any 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 Trigger tasks). See the @EnableScheduling javadocs for complete usage details.
@PostConstruct also implemented via post-processor InitDestroyAnnotationBeanPostProcessor when dependency injection performed for bean, method which marked @PostConstruct
will be executed thru reflection without proxy.
See InitDestroyAnnotationBeanPostProcessor source code
Summary:
In your example, Spring will create bean without proxy.
In case you will add a proxy-specific annotation, for example, @Transactional
you will get an exception that proxy can not be created due to final class java.lang.IllegalArgumentException: Cannot subclass final class com.test.services.MyService
@Service
@EnableScheduling
public final class MyService {
@PostConstruct
public void init(){
System.out.println("MyService started");
}
@Scheduled(fixedDelay= 1000)
@Transactional
public void scheduleCall() {
System.out.println("scheduleCall");
}
}
But the current problem you also can solve to force use JDK dynamic proxy
. We need to create an interface for class and set property spring.aop.proxy-target-class = false
according to Proxying mechanisms