【每日提高之声明式事物】spring声明式事务 同一类内方法调用事务失效
2019獨角獸企業重金招聘Python工程師標準>>>
【問題】
?????? Spring的聲明式事務,我想就不用多介紹了吧,一句話“自從用了Spring AOP啊,事務管理真輕松啊,真輕松;事務管理代碼沒有了,腦不酸了,手不痛了,一口氣全配上了事務;輕量級,測試起來也簡單,嘿!”。不管從哪個角度看,輕量級聲明式事務都是一件解放生產力的大好事。所以,我們“一直用它”。
????? 不過,最近的一個項目里,卻碰到了一個事務管理上的問題:有一個服務類,其一個聲明了事務的方法,里面做了三次插入SQL操作,但是在后面出錯回滾時,卻發現前面插入成功了,也是說,這個聲明了事務的方法,實際上并沒有真正啟動事務!怎么回事呢?難道Spring的聲明式事務失效了?
?
【分析】
? ? ?這個問題,表面上是事務聲明失效的問題,實質上很可能是Spring的AOP機制實現角度的問題。我想到很久以前研究Spring的AOP實現時發現的一個現象:對于以Cglib方式增強的AOP目標類,會創建兩個對象,一個事Bean實例本身,一個是Cglib增強代理對象,而不僅僅是只有后者。
? ? ?我們知道,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實現,應該是下面這樣:
使用代理
1、Proxy.insertAAA() 代理對象加了事物,這樣就可以增強事物。
public?void?a()?{??aopProxy.b();//即調用AOP代理對象的b方法即可執行事務切面進行事務增強??}??判斷一個Bean是否是AOP代理對象可以使用如下三種方法:
AopUtils.isAopProxy(bean)????????:?是否是代理對象;
AopUtils.isCglibProxy(bean)???????:?是否是CGLIB方式的代理對象;
AopUtils.isJdkDynamicProxy(bean)?:?是否是JDK動態代理方式的代理對象;
修改我們的代碼
this.b();-----------修改為--------->((AService) AopContext.currentProxy()).b();
?
在使用的過程中,提示錯誤:
關于AOP無法切入同類調用方法的問題,給方式使用注解@Transactional(propagation = Propagation.REQUIRED,
?? ?isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class)
文章參考:
https://blog.csdn.net/dapinxiaohuo/article/details/52092447
https://blog.csdn.net/aya19880214/article/details/50640596
轉載于:https://my.oschina.net/maojindaoGG/blog/1920783
總結
以上是生活随笔為你收集整理的【每日提高之声明式事物】spring声明式事务 同一类内方法调用事务失效的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Leetcode - Subsets I
- 下一篇: react源码分析-setState分析