假设我们有以下课程
@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()
。
我猜对了吗?非常感谢您的建议!
答案 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无法避免调用重写方法。