Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does spring create proxy for a final class?

Tags:

java

spring

cglib

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 ?

like image 380
gstackoverflow Avatar asked Jul 21 '26 07:07

gstackoverflow


1 Answers

@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.

@Scheduled

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

like image 192
Eugene Avatar answered Jul 22 '26 20:07

Eugene



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!