简体   繁体   English

同一类调用在Spring AOP cglib中无效

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM