>假设我们有以下类
@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 无法避免调用被覆盖的方法。