1. 程式人生 > >Spring 從同一個類中的某個方法呼叫另一個有註解(@Transactional)的方法時,失效的解決方案

Spring 從同一個類中的某個方法呼叫另一個有註解(@Transactional)的方法時,失效的解決方案

考慮有下面這麼一個類

public class Foo {
    @Transactional
    public void bar() { /* … */ }

    public void baz() {
        this.bar();
    }
}

可能會有不少人會跟我一樣,覺得上面這種方式呼叫 baz()方法時,bar()上的@Transactional註解還是會起作用的,即bar()在被呼叫時,將會開啟事務。
但是,當實際操作之後,你會發現,這樣並不會開啟新的事務?
為什麼呢?
我們知道,Spring之所以可以對開啟@Transactional的方法進行事務管理,是因為Spring為當前類生成了一個代理類,然後在執行相關方法時,會判斷這個方法有沒有@Transactional

註解,如果有的話,則會開啟一個事務。
但是,上面這種呼叫方式時,在呼叫baz()時,使用的並不是代理物件,從而導致this.bar()時也不是程式碼物件,從而導致@Transactional失敗。
那麼,對於這種情況,要怎麼處理呢?

首先,在spring的xml中加上如下配置

<aop:aspectj-autoproxy expose-proxy="true"/>

然後,在baz() 中,改成如下方式呼叫

public class Foo {

    @Timed
    public void bar() { /* … */ }

    public
void baz() { ((Foo) AopContext.currentProxy()).bar(); } }

PS: 如果是通過 “@Aspect” 註解實現的 AOP,那麼,暫時還沒有找到方法來解決

.

參考文件