目录
Spring动态代理(AOP)问题汇总
在同一个类中,一个方法调用另外一个动态代理方法(比如有@Async、@Transactional),动态代理是不会生效的,而@Configuration注解配置的类却可以代理(@Bean注解的方法)?
示例代码如下:
@Component
public class Example {
@Async
public String sayHello(String name) {
return "hi~ " + name;
}
@Async
public String sayGoodBye(String name) {
return sayHello(name) + " good bye";
}
}
@Configuration
public class BeanConfig {
@Bean
public T1 t1() {
return new T1();
}
@Bean
public String test1() {
return "test1" + t1();
}
@Bean
public String test2() {
return "test2" + t1();
}
public String test3() {
return "test3" + t1();
}
static class T1 {
}
}
我们知道cglib动态代理是通过继承父类,然后重写父类方法来实现代理的。根据java的多态性,重写了父类的方法,方法执行时肯定会执行子类的实现,也就是说动态代理会生效的。但是,结合上面的例子,我们发现@Async
注解的方法没有生效,但是@Bean
注解的方法却生效了。
原因: 我们可以先调试一下,@Bean
注解的方法this
对象是cglib增强的类的实例,而
@Async
注解的方法,在执行到方法内部时,this
对象不是cglib增强类的实例,所以动态代理不会生效。
我们在结合源代码分析,CglibMethodInvocation
调用链执行到最后执行invokeJoinpoint()
方法时,传入的对象确实是原来未增强的对象
另外@Configuration
注解的类是通过ConfigurationClassEnhancer#enhance
方法创建增强类的;而普通的AOP代理是通过ProxyFactory#getProxy
方法创建增强类的,它支持cglib和jdk代理这两种方式。