同一个类在Spring AOP cglib中调用无效

时间:2017-03-21 08:07:17

标签: java aop cglib

假设我们有以下课程

@Service
class MyClass {

    public void testA() { 
        testB();
     }

    @Transactional
    public void testB() { ... }
}

现在,如果我们在测试中调用myClass.testA();,则@Transactional上的testB将不会生效。我认为之所以如此。

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()

我猜对了吗?非常感谢您的建议!

2 个答案:

答案 0 :(得分:1)

这是一个众所周知的documented(请搜索术语"自我调用")事实,Spring AOP由于其基于代理的性质,不会也无法捕获内部方法调用如this.someMethod(..)

正如您所说,您需要明确引用公开的代理对象,或者从Spring AOP切换到完整AspectJ via load-time weaving

答案 1 :(得分:0)

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

class Cglib$MyClass extends MyClass {

  MyClass delegate;

  @Override
  public void testB() {
    // ...do transactional things
    delegate.testB();
  }
}

任何调用都由Spring转发,这就是为什么你的嵌套注释没有被激活。

此外,如果覆盖了testA之类的虚拟方法,则Spring无法避免调用重写方法。