一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - spring @Transactional 無效的解決方案

spring @Transactional 無效的解決方案

2021-07-26 10:40dezun Java教程

這篇文章主要介紹了spring @Transactional 無效的解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

關于@transactional注解 一般都認為要注意以下三點

1 .在需要事務管理的地方加@transactional 注解。@transactional 注解可以被應用于接口定義和接口方法、類定義和類的 public 方法上 。

2 . @transactional 注解只能應用到 public 可見度的方法上 。 如果你在 protected、private 或者 package-visible 的方法上使用 @transactional 注解,它也不會報錯, 但是這個被注解的方法將不會展示已配置的事務設置。

3 . 注意僅僅 @transactional 注解的出現不足于開啟事務行為,它僅僅 是一種元數據。必須在配置文件中使用配置元素,才真正開啟了事務行為。

最近在項目中發現注解無效,經過跟蹤源代碼發現了問題,于是在網上找到相同出現此問題的人,以下為原文,講解的很詳細:

只要避開spring目前的aop實現上的限制,要么都聲明要事務,要么分開成兩個類,要么直接在方法里使用編程式事務

[問題]

spring的聲明式事務,我想就不用多介紹了吧,一句話“自從用了spring aop啊,事務管理真輕松啊,真輕松;事務管理代碼沒有了,腦不酸了,手不痛了,一口氣全配上了事務;輕量級,測試起來也簡單,嘿!”。不管從哪個角度看,輕量級聲明式事務都是一件解放生產力的大好事。所以,我們“一直用它”。

不過,最近的一個項目里,卻碰到了一個事務管理上的問題:有一個服務類,其一個聲明了事務的方法,里面做了三次插入sql操作,但是在后面出錯回滾時,卻發現前面插入成功了,也是說,這個聲明了事務的方法,實際上并沒有真正啟動事務!怎么回事呢?難道spring的聲明式事務失效了?

[探幽]

其實以前也會碰到有人說,spring的事務配置不起作用,但是根據第一反應和以往經驗,我總會告訴他,肯定是你的配置有問題啦;所以這一次,我想也不會例外,大概是把事務注解配在了接口上而不是實現方法上,或者,如果是用xml聲明方式的話,很可能是切入點的表達式沒有配對。

 不過,在檢查了他們的配置后,卻發現沒有配置問題,該起事務的實現方法上,用了@transactional事務注解聲明,xml里也配了注解驅動<tx:annotation-driven .../>,配置很正確啊,怎么會不起作用?

我很納悶,于是往下問:

問1:其他方法有這種情況么?

答1:沒有。

問2:這個方法有什么特別的么(以下簡稱方法b)?

答2:就是調后臺插了三條記錄啊,沒啥特別的。

問3:這個方法是從web層直接調用的吧?

答3:不是,是這個service類(以下簡稱servicea)的另外一個方法調過來的(以下簡稱方法a)。

問4:哦,那個調用它的方法配了事務么(問題可能在這了)?

 答4:沒有。

問5:那web層的action(用的是struts2),調用的是沒有聲明事務的方法a,方法a再調用聲明了事務的方法b?

答5:對的。

問6:你直接在方法a上加上事務聲明看看

答6:好。。。

看來可能找到問題所在了,于是把@transactional也加在方法a上,啟動項目測試,結果是:事務正常生效,方法a和方法b都在一個事務里了。

好了,現在總結一下現象:

1、servicea類為web層的action服務

2、action調用了servicea的方法a,而方法a沒有聲明事務(原因是方法a本身比較耗時而又不需要事務)

3、servicea的方法a調用了自己所在class的方法b,而方法b聲明了事務,但是方法b的事務聲明在這種情況失效了。

4、如果在方法a上也聲明事務,則在action調用方法a時,事務生效,而方法b則自動參與了這個事務。

我讓他先把a也加上事務聲明,決定回來自己再測一下。

這個問題,表面上是事務聲明失效的問題,實質上很可能是spring的aop機制實現角度的問題。

我想到很久以前研究spring的aop實現時發現的一個現象:對于以cglib方式增強的aop目標類,會創建兩個對象,一個事bean實例本身,一個是cglib增強代理對象,而不僅僅是只有后者。我曾經疑惑過這一點,但當時沒有再仔細探究下去。

 我們知道,spring的aop實現方式有兩種:1、java代理方式;2、cglib動態增強方式,這兩種方式在spring中是可以無縫自由切換的。

java代理方式的優點是不依賴第三方jar包,缺點是不能代理類,只能代理接口。

spring通過aopproxy接口,抽象了這兩種實現,實現了一致的aop方式:

spring @Transactional 無效的解決方案

現在看來,這種抽象同樣帶了一個缺陷,那就是抹殺了cglib能夠直接創建普通類的增強子類的能力,spring相當于把cglib動態生成的子類,當普通的代理類了,這也是為什么會創建兩個對象的原因。下圖顯示了spring的aop代理類的實際調用過程:

spring @Transactional 無效的解決方案

因此,從上面的分析可以看出,methodb沒有被aopproxy通知到, 導致最終結果是:

被spring的aop增強的類,在同一個類的內部方法調用時,其被調用方法上的增強通知將不起作用。

而這種結果,會造成什么影響呢: 1:內部調用時,被調用方法的事務聲明將不起作用 2:換句話說,你在某個方法上聲明它需要事務的時候,如果這個類還有其他開發者,你將不能保證這個方法真的會在事務環境中 3:再換句話說,spring的事務傳播策略在內部方法調用時將不起作用。

不管你希望某個方法需要單獨事務,是requiresnew,還是要嵌套事務,要nested,等等,統統不起作用。
4:不僅僅是事務通知,所有你自己利用spring實現的aop通知,都會受到同樣限制。。。。

[解難]

問題的原因已經找到,其實,我理想中的aop實現,應該是下面這樣:

spring @Transactional 無效的解決方案

只要一個cglib增強對象就好,對于java代理方式,我的選擇是毫不猶豫的拋棄。

至于前面的事務問題,只要避開spring目前的aop實現上的限制,要么都聲明要事務,要么分開成兩個類,要么直接在方法里使用編程式事務,那么一切ok。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/gudejundd/article/details/54380141

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产亚洲精品美女2020久久 | 国产区综合另类亚洲欧美 | 国内精品九一在线播放 | 视频在线播放 | 亚洲剧情在线 | 日韩精品成人在线 | 99撸| 亚洲精品视频网 | 美女林柏欣21p人体之仓之梦 | 国产区成人综合色在线 | 秋霞在线观看成人高清视频51 | 91免费在线| 亚洲一区二区三区91 | 日本在线看 | 99久女女精品视频在线观看 | 四虎现在的网址入口2022 | 精品在线观看一区 | 亚洲欧美综合一区 | 欧美日韩亚洲国内综合网俺 | 赤坂丽女医bd无删减在线观看 | 国产在视频线在精品 | 我们中文在线观看免费完整版 | 干露露视频 性感写真 | 免费一级毛片完整版在线看 | 亚洲国产午夜看片 | 国产一二在线观看视频网站 | 精精国产xxxx视频在线播放器 | 无码一区二区三区视频 | 特大黑人娇小亚洲女mp4 | 国产偷窥女洗浴在线观看亚洲 | 青青青在线免费 | freexxxxxhd张柏芝 | 果冻传媒天美传媒乌鸦传媒 | 精品麻豆国产 | 免费观看成年肉动漫网站 | 美女撒尿无遮挡免费中国 | 色综合天天综合中文网 | 小舞丝袜调教喷水沦为肉奴 | 亚洲2023无矿砖码砖区 | haodiaocao几万部精彩视频 | 成人看片免费无限观看视频 |