[英]Same class invoke NOT effective in Spring AOP cglib
Suppose we have following class 假设我们有以下课程
@Service
class MyClass {
public void testA() {
testB();
}
@Transactional
public void testB() { ... }
}
Now, if we invoke myClass.testA();
现在,如果我们调用
myClass.testA();
in test, then @Transactional
on testB
will not take effect. 在测试中,那么
testB
@Transactional
不会生效。 The reason I think is following. 我认为的原因如下。
Cglib will create a proxy bean for MyClass
, like this: Cglib将为
MyClass
创建一个代理bean,如下所示:
Class Cglib$MyClass extends MyClass {
@Override
public void testB() {
// ...do transactional things
super.testB();
}
}
Now we invoke myClass.testA()
, which will invoke MyClass.testB()
instead of Cglib$MyClass.testB()
. 现在我们调用
myClass.testA()
,它将调用MyClass.testB()
而不是Cglib$MyClass.testB()
。 So @Transactional
is not effective. 因此,@
@Transactional
无效。 (Am I right?) (我对吗?)
I tried to add @Transactional
for both methods (ie testA()
and testB()
). 我试图为两种方法(即
testA()
和testB()
)添加@Transactional
。 The proxy class should like this. 代理类应该这样。
Class Cglib$MyClass extends MyClass {
@Override
public void testA() {
// ...do transactional things
super.testA();
}
@Override
public void testB() {
// ...do transactional things
super.testB();
}
}
In this case, although we successfully invoke Cglib$MyClass.testA()
, it will still goes to MyClass.testB()
. 在这种情况下,尽管我们成功调用了
Cglib$MyClass.testA()
,但它仍将移至MyClass.testB()
。
So my conclusion is, two methods in same class invoking each other will make aop annotation fail to take effect, unless we use AopContext.currentProxy()
. 因此,我的结论是,除非使用
AopContext.currentProxy()
,否则同一类中的两个方法相互调用将使aop注释无法生效。
Am I right on above guess? 我猜对了吗? Thanks very much for advice!
非常感谢您的建议!
It is a well-known and documented (please search for the term "self-invocation") fact that Spring AOP, due to its proxy-based nature, does not and cannot capture internal method calls like this.someMethod(..)
. 众所周知,Spring AOP由于其基于代理的性质而不能并且不能捕获诸如
this.someMethod(..)
类的内部方法调用,这是众所周知的且有据可查的事实(请搜索“ self-invocation”一词this.someMethod(..)
。
So as you said, you either need to explicitly refer to the exposed proxy object or alternatively switch from Spring AOP to full AspectJ via load-time weaving . 因此,正如您所说,您要么需要显式引用公开的代理对象,要么通过加载时编织从Spring AOP切换到完整的AspectJ 。
You almost have it right. 您几乎是正确的。 The proxy looks something more like this:
代理看起来像这样:
class Cglib$MyClass extends MyClass {
MyClass delegate;
@Override
public void testB() {
// ...do transactional things
delegate.testB();
}
}
Any call is forwarded by Spring which is why your nested annotations are not activated. Spring会转发任何呼叫,这就是为什么您的嵌套注释未激活的原因。
Also, if a virtual method like testA
was overridden, Spring could not avoid to invoke the overridden method. 同样,如果像
testA
这样的虚拟方法被覆盖,Spring testA
避免调用被覆盖的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.