Spring 事務實現原理 (同一個類方法調用事務失效)

Spring 聲明式事務實現原理

  • 起因
    本人之前使用Spring事務時遇到兩種場景。同一個class沒有事務的A方法調用含有事務的B方法發現事務不生效,同一個class有事務的A方法調用含有事務的B方法(傳播性爲REQUIRES_NEW),獨立事務也沒有創建。
    一切的原因就和 Spring 利用 AOP 代理實現聲明式事務緊密關聯了。

  • 原因
    我們知道,Spring的AOP實現方式有兩種:1、Java代理方式;2、Cglib動態增強方式,這兩種方式在Spring中是可以無縫自由切換的。Java代理方式的優點是不依賴第三方jar包,缺點是不能代理類,只能代理接口。Spring通過AopProxy接口,抽象了這兩種實現,實現了一致的AOP方式:
    這裏寫圖片描述
    現在看來,這種抽象同樣帶了一個缺陷,那就是抹殺了Cglib能夠直接創建普通類的增強子類的能力,Spring相當於把Cglib動態生成的子類,當普通的代理類了,這也是爲什麼會創建兩個對象的原因。下圖顯示了Spring的AOP代理類的實際調用過程:
    這裏寫圖片描述
    因此,從上面的分析可以看出,methodB沒有被AopProxy通知到,導致最終結果是:被Spring的AOP增強的類,在同一個類的內部方法調用時,其被調用方法上的增強通知將不起作用。

    而這種結果,會造成什麼影響呢:
    1:內部調用時,被調用方法的事務聲明將不起作用
    2:換句話說,你在某個方法上聲明它需要事務的時候,如果這個類還有其他開發者,你將不能保證這個方法真的會在事務環境中
    3:再換句話說,Spring的事務傳播策略在內部方法調用時將不起作用。不管你希望某個方法需要單獨事務,是RequiresNew,還是要嵌套事務,要Nested,等等,統統不起作用。
    4:不僅僅是事務通知,所有你自己利用Spring實現的AOP通知,都會受到同樣限制。。。。

    問題的原因已經找到,其實,我理想中的AOP實現,應該是下面這樣:
    這裏寫圖片描述
    只要一個Cglib增強對象就好,對於Java代理方式,我的選擇是毫不猶豫的拋棄。

    至於前面的事務問題,只要避開Spring目前的AOP實現上的限制,要麼都聲明要事務,要麼分開成兩個類,要麼直接在方法裏使用編程式事務,那麼一切OK。

    解釋內容轉載自:https://blog.csdn.net/seelye/article/details/40144817

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章