spring如何为final类创建代理?

gst*_*low 7 java spring cglib

也许我有一些过时的知识,但它与此处描述的相同 /sf/answers/186022581/

但现在我注意到这个例子可以正常工作,没有任何异常:

@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");    
 
  }
}
Run Code Online (Sandbox Code Playgroud)

您能提供一下它是如何工作的吗?

Eug*_*ene 13

@Scheduled注解不需要创建代理。机制不同。bean 初始化后,Spring 调用后处理器ScheduledAnnotationBeanPostProcessor。后处理器会搜索所有带注释的方法@Scheduled,并将其注册到TaskScheduler中执行。方法执行将通过反射来执行。
请参阅ScheduledAnnotationBeanPostProcessor 源代码

@预定

@Scheduled 注解的处理是通过注册 ScheduledAnnotationBeanPostProcessor 来执行的。这可以手动完成,或者更方便地通过 task:annotation-driven/ XML 元素或 @EnableScheduling 注释完成。

ScheduledAnnotationBean后处理器

Bean 后处理器,注册用 @Scheduled 注释的方法,以便 TaskScheduler 根据通过注释提供的“fixedRate”、“fixedDelay”或“cron”表达式来调用。该后处理器由 Spring 的 task:annotation-driven XML 元素以及 @EnableScheduling 注释自动注册。

自动检测容器中的任何 SchedulingConfigurer 实例,允许自定义要使用的调度程序或对任务注册进行细粒度控制(例如,触发任务的注册)。有关完整的使用详细信息,请参阅 @EnableScheduling javadocs。

当对bean执行依赖注入时,@PostConstruct也通过后处理器InitDestroyAnnotationBeanPostProcessor@PostConstruct实现,标记的方法将通过反射执行,无需代理。
查看InitDestroyAnnotationBeanPostProcessor源代码

摘要:
在您的示例中,Spring 将创建没有代理的 bean。

例如,如果您要添加特定于代理的注释,@Transactional您将收到由于最终类而无法创建代理的异常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");

    }
}
Run Code Online (Sandbox Code Playgroud)

但目前的问题你也可以通过强制使用来解决JDK dynamic proxy。我们需要为类创建一个接口并spring.aop.proxy-target-class = false根据代理机制设置属性