Suppose we have following class
@Service
class MyClass {
public void testA() {
testB();
}
@Transactional
public void testB() { ... }
}
Now, if we invoke myClass.testA();
in test, then @Transactional
on testB
will not take effect. The reason I think is following.
Cglib will create a proxy bean for MyClass
, like this:
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()
. So @Transactional
is not effective. (Am I right?)
I tried to add @Transactional
for both methods (i.e. testA()
and testB()
). 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()
.
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()
.
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(..)
.
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.
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.
Also, if a virtual method like testA
was overridden, Spring could not avoid to invoke the overridden method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With