2017-03-21 53 views
0

假設我們有以下同一類在Spring AOP CGLIB調用沒有效果

@Service 
class MyClass { 

    public void testA() { 
     testB(); 
    } 

    @Transactional 
    public void testB() { ... } 
} 

現在,如果我們在測試調用myClass.testA();,然後@TransactionaltestB不會生效。我認爲的原因在於。

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是無效的。 (對嗎?)

我試着爲兩種方法(即testA()testB())添加@Transactional。代理類應該這樣。

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

我對上述猜測是否正確?非常感謝您的建議!

回答

0

你幾乎沒錯。代理看起來更像這樣:

class Cglib$MyClass extends MyClass { 

    MyClass delegate; 

    @Override 
    public void testB() { 
    // ...do transactional things 
    delegate.testB(); 
    } 
} 

任何調用被Spring轉發,這就是爲什麼你的嵌套註釋沒有被激活。另外,如果像testA這樣的虛擬方法被覆蓋,Spring無法避免調用重寫的方法。

0

這是一個衆所周知的和documented(請搜索術語「自我調用」)事實,即Spring AOP由於其基於代理的性質,不能捕獲像this.someMethod(..)這樣的內部方法調用。

因此,如您所說,您需要明確引用暴露的代理對象,或者從Spring AOP切換到完整AspectJ via load-time weaving