Same class invoke NOT effective in Spring AOP cglib

时间秒杀一切 提交于 2020-01-13 19:56:14

问题


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!


回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/42921388/same-class-invoke-not-effective-in-spring-aop-cglib

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!