一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

 昵稱11935121 2018-06-12

原創(chuàng):徐劉根

一、場(chǎng)景分析

最近做項(xiàng)目遇到了一個(gè)很奇怪的問(wèn)題,大致的業(yè)務(wù)場(chǎng)景是這樣的:我們首先設(shè)定兩個(gè)事務(wù),事務(wù)parent和事務(wù)child,在Controller里邊同時(shí)調(diào)用這兩個(gè)方法,示例代碼如下:

1、場(chǎng)景A:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

這里其實(shí)是分別執(zhí)行了兩個(gè)事物,執(zhí)行的結(jié)果是兩個(gè)方法都可以插入數(shù)據(jù)!如下:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

2、場(chǎng)景B:

修改上述代碼如下:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

Propagation.REQUIRES_NEW的含義表示:如果當(dāng)前存在事務(wù),則掛起當(dāng)前事務(wù)并且開(kāi)啟一個(gè)新事物繼續(xù)執(zhí)行,新事物執(zhí)行完畢之后,然后在緩刑之前掛起的事務(wù),如果當(dāng)前不存在事務(wù)的話,則開(kāi)啟一個(gè)新事物。

執(zhí)行的結(jié)果是兩個(gè)方法都可以插入數(shù)據(jù)!執(zhí)行結(jié)果如下:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

場(chǎng)景A和場(chǎng)景B都是正常的執(zhí)行,期間沒(méi)有發(fā)生任何的回滾,假如child()方法中出現(xiàn)了異常!

3、場(chǎng)景C

修改child()的代碼如下所示,其他代碼和場(chǎng)景B一樣:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

執(zhí)行結(jié)果如下,會(huì)出現(xiàn)異常,并且數(shù)據(jù)都沒(méi)有插入進(jìn)去:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

疑問(wèn)1:場(chǎng)景C中child()拋出了異常,但是parent()沒(méi)有拋出異常,按道理是不是應(yīng)該parent()提交成功而child()回滾?

可能有的小伙伴要說(shuō)了,child()拋出了異常在parent()沒(méi)有進(jìn)行捕獲,造成了parent()也是拋出了異常了的!所以他們兩個(gè)都會(huì)回滾!

4、場(chǎng)景D

按照上述小伙伴的疑問(wèn)這個(gè)時(shí)候,如果對(duì)parent()方法修改,捕獲child()中拋出的異常,其他代碼和場(chǎng)景C一樣:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

然后再次執(zhí)行,結(jié)果是兩個(gè)都插入了數(shù)據(jù)庫(kù):

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

看到這里很多小伙伴都可能會(huì)問(wèn),按照我們的邏輯來(lái)想的話child()中拋出了異常,parent()沒(méi)有拋出并且捕獲了child()拋出了異常!執(zhí)行的結(jié)果應(yīng)該是child()回滾,parent()提交成功的?。?/p>

疑問(wèn)2:場(chǎng)景D為什么不是child()回滾和parent()提交成功哪?

上述的場(chǎng)景C和場(chǎng)景D似乎融為了一題,要么都成功要么都失?。『臀覀冾A(yù)期的效果一點(diǎn)都不一樣!看到這里這就是我們今天要探討的主題《JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑!》接下來(lái)我們就分析一下Spring事物在該特定場(chǎng)景下不能回滾的深層次原因!

二、問(wèn)題本質(zhì)所在

我們知道Spring事務(wù)管理是通過(guò)JDK動(dòng)態(tài)代理的方式進(jìn)行實(shí)現(xiàn)的(另一種是使用CGLib動(dòng)態(tài)代理實(shí)現(xiàn)的),也正是因?yàn)閯?dòng)態(tài)代理的特性造成了上述parent()方法調(diào)用child()方法的時(shí)候造成了child()方法中的事務(wù)失效!簡(jiǎn)單的來(lái)說(shuō),在場(chǎng)景D中parent()方法調(diào)用child()方法的時(shí)候,child()方法的事務(wù)是不起作用的,此時(shí)的child()方法像一個(gè)沒(méi)有加事務(wù)的普通方法,其本質(zhì)上就相當(dāng)于下邊的代碼:

場(chǎng)景C本質(zhì):

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

場(chǎng)景D本質(zhì):

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

正如上述的代碼,我們可以很輕松的解釋疑問(wèn)1和疑問(wèn)2,因?yàn)閯?dòng)態(tài)代理的特性造成了場(chǎng)景C和場(chǎng)景D的本質(zhì)如上述代碼。在場(chǎng)景C中,child()拋出異常沒(méi)有捕獲,相當(dāng)于parent事務(wù)中拋出了異常,造成parent()一起回滾,因?yàn)樗麄儽举|(zhì)是同一個(gè)方法;在場(chǎng)景D中,child()拋出異常并進(jìn)行了捕獲,parent事務(wù)中沒(méi)有拋出異常,parent()和child()同時(shí)在一個(gè)事務(wù)里邊,所以他們都成功了;

看到這里,那么動(dòng)態(tài)代理的這個(gè)特性到底是什么才會(huì)造成Spring事務(wù)失效那?

三、動(dòng)態(tài)代理的這個(gè)特性到底是什么?

首先我們看一下一個(gè)簡(jiǎn)單的動(dòng)態(tài)代理實(shí)現(xiàn)方式:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

此時(shí)我們執(zhí)行以下測(cè)試方法,注意了此時(shí)是同時(shí)調(diào)用了test1()和test2()的,執(zhí)行結(jié)果如下:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

可以看出,在OrderServiceImpl 類中由于test1()沒(méi)有調(diào)用test2(),他們方法的執(zhí)行都是使用了代理的,也就是說(shuō)test1和test2都是通過(guò)代理對(duì)象調(diào)用的invoke()方法,這和我們場(chǎng)景A和B類似。

加入我們模擬一下場(chǎng)景C和場(chǎng)景D在test1()中調(diào)用test2(),那么代碼修改為如下:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

執(zhí)行結(jié)果如下:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

這里可以很清楚的看出來(lái)test1()走的是代理,而test2()走的是普通的方法,沒(méi)有經(jīng)過(guò)代理!看到這里你是否已經(jīng)恍然大明白了呢?

這個(gè)應(yīng)該可以很好的理解為什么是這樣子!這是因?yàn)樵贘ava中test1()中調(diào)用test2()中的方法,本質(zhì)上就相當(dāng)于把test2()的方法體放入到test1()中,也就是內(nèi)部方法,同樣的不管你嵌套了多少層,只有代理對(duì)象proxy 直接調(diào)用的那一個(gè)方法才是真正的走代理的,如下:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

測(cè)試方法和上邊的測(cè)試方法一樣,執(zhí)行結(jié)果如下:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

記住:只有代理對(duì)象proxy直接調(diào)用的那個(gè)方法才是真正的走代理的!

四、如何解決這個(gè)坑?

上文的分析中我們已經(jīng)了解了為什么在該特定場(chǎng)景下使用Spring事務(wù)的時(shí)候造成事務(wù)無(wú)法回滾的問(wèn)題,下邊我們談一下幾種解決的方法:

1、我們可以選擇逃避這個(gè)問(wèn)題!我們可以不使用以上這種事務(wù)嵌套的方式來(lái)解決問(wèn)題,最簡(jiǎn)單的方法就是把問(wèn)題提到Service或者是更靠前的邏輯中去解決,使用service.xxxtransaction是不會(huì)出現(xiàn)這種問(wèn)題的。

2、通過(guò)AopProxy上下文獲取代理對(duì)象:

(1)SpringBoot配置方式:注解開(kāi)啟 exposeProxy = true,暴露代理對(duì)象 (否則AopContext.currentProxy()) 會(huì)拋出異常。

添加依賴:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

添加注解:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

修改原有代碼的執(zhí)行方式為:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

此時(shí)的執(zhí)行結(jié)果為:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

可見(jiàn),child方法由于異常已經(jīng)回滾了,而parent可以正確的提交,這才是我們想要的結(jié)果!注意的是在parent調(diào)用child的時(shí)候是通過(guò)try/catch捕獲了異常的!

(2)傳統(tǒng)Spring XML配置文件只需要添加依賴個(gè)設(shè)置如下配置即可,使用方式一樣:

3、通過(guò)ApplicationContext上下文進(jìn)行解決:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

執(zhí)行結(jié)果符合我們的預(yù)期:

「每日分享」面試必備技能:JDK動(dòng)態(tài)代理給Spring事務(wù)埋下的坑

五、總結(jié)

到此為止,我們簡(jiǎn)單的介紹了一下Spring事務(wù)管理中如果業(yè)務(wù)中有像場(chǎng)景C或者場(chǎng)景D的情況時(shí),如果不清楚JDK動(dòng)態(tài)代理造成Spring事務(wù)無(wú)法回滾的問(wèn)題的話就可能是一個(gè)開(kāi)發(fā)事故了,說(shuō)不定是要扣工資的!

上文中簡(jiǎn)述了幾種場(chǎng)景的事務(wù)使用和造成事務(wù)無(wú)法回滾的根本問(wèn)題,當(dāng)然講述的還是表面的現(xiàn)象,并沒(méi)有深入原理去分析,盡管如此,如果你在面試的時(shí)候能夠?qū)@個(gè)問(wèn)題說(shuō)一下自己的了解,也是一個(gè)加分項(xiàng)!

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    中文字幕乱码亚洲三区| 色无极东京热男人的天堂| 日本加勒比不卡二三四区| 日韩人妻中文字幕精品| 久热香蕉精品视频在线播放| 亚洲中文字幕在线视频频道| 日韩午夜福利高清在线观看| 国产精品尹人香蕉综合网| 国产精品久久精品毛片| 色综合视频一区二区观看| 亚洲国产精品久久网午夜| 后入美臀少妇一区二区| 香港国产三级久久精品三级| 男生和女生哪个更好色| 日韩精品一区二区一牛| 亚洲欧美日韩国产成人| 亚洲欧洲日韩综合二区| 成人你懂的在线免费视频| 欧美在线视频一区观看| 沐浴偷拍一区二区视频| 国产精品人妻熟女毛片av久 | 亚洲精品成人综合色在线| 在线欧美精品二区三区| 黄色国产精品一区二区三区| 午夜福利在线观看免费| 激情五月激情婷婷丁香| 最新69国产精品视频| 久久99精品国产麻豆婷婷洗澡| 美女极度色诱视频在线观看| 亚洲欧美视频欧美视频| 爱草草在线观看免费视频| 99热九九在线中文字幕| 亚洲av日韩av高潮无打码| 欧美黄色黑人一区二区| 亚洲成人免费天堂诱惑| 日韩免费国产91在线| 人妻熟女欲求不满一区二区| 中文精品人妻一区二区| 午夜精品国产精品久久久| 国产麻豆一区二区三区在| 肥白女人日韩中文视频|