【问题标题】:Same class invoke NOT effective in Spring AOP cglib [duplicate]相同的类调用在 Spring AOP cglib 中无效 [重复]
【发布时间】:2017-03-21 08:07:17
【问题描述】:

假设我们有以下类

@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()

我猜对了吗?非常感谢您的建议!

【问题讨论】:

    标签: java aop cglib


    【解决方案1】:

    众所周知,documented(请搜索术语“自调用”)事实是 Spring AOP,由于其基于代理的性质,不会也无法捕获像 this.someMethod(..) 这样的内部方法调用.

    正如你所说,你要么需要显式引用暴露的代理对象,要么从 Spring AOP 切换到完整的AspectJ via load-time weaving

    【讨论】:

      【解决方案2】:

      你几乎说对了。代理看起来更像这样:

      class Cglib$MyClass extends MyClass {
      
        MyClass delegate;
      
        @Override
        public void testB() {
          // ...do transactional things
          delegate.testB();
        }
      }
      

      任何调用都由 Spring 转发,这就是您的嵌套注释未激活的原因。

      另外,如果像testA 这样的虚方法被覆盖,Spring 无法避免调用被覆盖的方法。

      【讨论】:

        猜你喜欢
        • 2015-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多