同一类调用在春季AOP cglib中无效



>假设我们有以下类

@Service
class MyClass {
    public void testA() { 
        testB();
     }
    @Transactional
    public void testB() { ... }
}

现在,如果我们在测试中调用myClass.testA();,那么testB @Transactional将不会生效。我认为原因是以下。

Cglib 将为 MyClass 创建一个代理 bean,如下所示:

Class Cglib$MyClass extends MyClass {
    @Override
    public void testB() {
        // ...do transactional things
        super.testB();
    }
}

现在我们调用 myClass.testA() ,它将调用 MyClass.testB() 而不是 Cglib$MyClass.testB() 。所以@Transactional是无效的。(我说的对吗?

我试图为这两种方法添加@Transactional(即 testA()testB()(。代理类应该像这样。

Class Cglib$MyClass extends MyClass {
    @Override
    public void testA() {
        // ...do transactional things
        super.testA();
    }
    @Override
    public void testB() {
        // ...do transactional things
        super.testB();
    }
}

在这种情况下,尽管我们成功调用了Cglib$MyClass.testA(),它仍然会转到 MyClass.testB() .

所以我的结论是,同一类中的两个方法相互调用会使 aop 注解无法生效,除非我们使用 AopContext.currentProxy()

我上面的猜测是对的吗?非常感谢您的建议!

一个众所周知且有据可查的(请搜索术语"自我调用"(事实是,Spring AOP 由于其基于代理的性质,不会也无法像 this.someMethod(..) 那样捕获内部方法调用。

所以正如你所说,你要么需要显式引用暴露的代理对象,要么通过加载时编织从Spring AOP切换到完整的AspectJ。

你几乎是对的。代理看起来更像这样:

class Cglib$MyClass extends MyClass {
  MyClass delegate;
  @Override
  public void testB() {
    // ...do transactional things
    delegate.testB();
  }
}

任何调用都由 Spring 转发,这就是您的嵌套注释未激活的原因。

此外,如果像 testA 这样的虚拟方法被覆盖,Spring 无法避免调用被覆盖的方法。

最新更新