为什么同一个类里的方法互相调用,AOP 切面和事务就不生效了?怎么修?代理对象上的字段为什么是 null?这篇在 Spring Framework 7.0.9 上逐项验证。
(a)普通的自调用 this.b() → 外部直接调 b():拦截 1 次;经过 a() 间接调 b():拦截 0 次
外部调 b() 时目标方法里的 this:this 是代理?false,this.getClass()=Svc(proxy 把调用转给了目标对象,this 是目标,不是代理)内部调用的 this 是目标对象,不经过代理。
(b)注入自己的代理(@Autowired @Lazy self) → 外部直接调 b():拦截 1 次;经过 a() 间接调 b():拦截 1 次
(c)AopContext.currentProxy()(exposeProxy=true) → 外部直接调 b():拦截 1 次;经过 a() 间接调 b():拦截 1 次
没有 exposeProxy=true(或不是代理对象)时 AopContext.currentProxy() → IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available, and ensure that AopContext.currentProxy() is invoked in the same thread as the AOP invocation context.
(d)拆成两个 Bean(Other 调 svc.b()) → 外部直接调 b():拦截 1 次;经过 a() 间接调 b():拦截 1 次注入自己的代理、AopContext.currentProxy() 或者拆成两个 Bean。
通过代理读 public 字段 s.field = null(目标对象里是 "字段值");这个 Bean 的类:Main$Svc·CGLIB(AopUtils.isAopProxy=true) 目标对象上读 field = 字段值
代理对象的字段不会被初始化,读字段要通过 getter。