Spring聲明式事務(wù)的一個注意點(diǎn)及原理簡析

以前我們說過默穴,Spring通過ThreadLocal機(jī)制解除了事務(wù)管理模塊與數(shù)據(jù)訪問層的緊密耦合床绪,提高了模塊的可重用性,也保證了多線程環(huán)境下的對connection資源的有效管理,實(shí)現(xiàn)了線程安全。而要將事務(wù)管理代碼從整個業(yè)務(wù)邏輯中抽離出來巫俺,提供系統(tǒng)性的服務(wù),就要使用Spring aop肿男,在使用過程中介汹,我們千萬不可忘記了其動態(tài)代理的實(shí)質(zhì),不然在使用過程你會不知不覺掉進(jìn)陷阱里舶沛,請看以下例子:

(1) 正常情況

外部調(diào)用:

orderService.addOrder(order,orderDto);   

Service內(nèi)的addOrder方法:

 @Override

 @Transactional

public void addOrder(Order order,OrderDto orderDto) throws Exception {

 orderDAO.addOrder(order);

 OrderDetail orderDetail = new OrderDetail();

 orderDetail.setDiscount(orderDto.getDiscount());

 orderDetail.setQuantity(orderDto.getQuantity());

 Product productParam = new Product();

 productParam.setProductId(orderDto.getProductId());

 Product productGet = productService.getProducts(productParam).get(0);

 orderDetail.setProduct(productGet);

 productGet.getOrderDetail().add(orderDetail);

 orderDetail.setOrder(order);

 order.getOrderDetails().add(orderDetail);

productGet.setQuantity(productGet.getQuantity()-orderDetail.getQuantity());

  orderDetailDAO.addOrderDetail(orderDetail);        

  throw new RuntimeException("it's wrong");

}   

添加訂單前數(shù)據(jù):

image

添加訂單后數(shù)據(jù):

image

拋出異常嘹承,事務(wù)回滾,操作后表記錄未變如庭。

(2) 非正常情況

外部調(diào)用:

orderService.addOrderWrapper(order,orderDto);

@Override

public void addOrderWrapper(Order order,OrderDto orderDto) throws Exception{

//(1)中的addOrder方法,仍然有@Transactional注解

 addOrder(order, orderDto);

}

執(zhí)行后數(shù)據(jù)

image

雖然拋出異常叹卷,但事務(wù)未回滾,操作后數(shù)據(jù)改變了。

為什么在orderService的addOrderWrapper()方法內(nèi)部調(diào)用addOrder(),報運(yùn)行時異常時就不會回滾了呢? 實(shí)際上豪娜,在第一種情況中餐胀,程序是通過orderService的代理類上調(diào)用addOrder()方法的哟楷,這樣瘤载,與該方法相關(guān)的攔截器就會對請求進(jìn)行攔截處理,提供相應(yīng)的事務(wù)處理機(jī)制卖擅;而在第二種情況下鸣奔,addOrder()方法雖然仍然有@Transaction注解,但僅僅是在orderService上的直接調(diào)用惩阶,而不是通過代理類調(diào)用挎狸,偽代碼的形式展現(xiàn)如下:

第一種情況:

ProxyFactory factory = new ProxyFactory(orderServiceImpl);

factory.addInterceptor(transactionInterceptor);

OrderService proxy = (orderService) factory.getProxy();

proxy.addOrder();//通過代理調(diào)用

第二種情況:

同this.addOrder();//直接通過this調(diào)用,事務(wù)攔截方法不起作用断楷。

在事務(wù)代理類上調(diào)用方法的過程見如圖:

image

(圖1-1 來源:spring-framework-reference)

無論Spring聲明式事務(wù)使用什么形式(基于Xml配置文件或者Annotation),萬變不離其宗,其底層都是使用了TransactionInterceptor锨匆。TransactionInterceptor是一個實(shí)現(xiàn)了MethodInterceptor接口的攔截器(Advice),具有相應(yīng)的事務(wù)橫切邏輯冬筒,被織入到系統(tǒng)中恐锣。若方法聲明了相應(yīng)的事務(wù)控制信息,它會在該方法執(zhí)行前開啟一個事務(wù)舞痰,完成時提交事務(wù)土榴,發(fā)生異常時回滾事務(wù),至于其中的具體規(guī)則(傳播响牛,隔離級別玷禽,超時時間,是否只讀呀打,針對何種異常進(jìn)行回滾)矢赁,可以通過xml或者@Transactional指定。

如圖就是它實(shí)現(xiàn)的invoke方法的源代碼:

image

createTransactionIfNecessary方法將會開啟一個事務(wù)贬丛;斷點(diǎn)處的proceed方法讓程序沿著調(diào)用鏈傳播(如圖1-1所示)撩银。completeTransactionAfterThrowing和commitTransactionAfterReturning方法則提交回滾事務(wù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末瘫寝,一起剝皮案震驚了整個濱河市蜒蕾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌焕阿,老刑警劉巖咪啡,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異暮屡,居然都是意外死亡撤摸,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來准夷,“玉大人钥飞,你說我怎么就攤上這事∩狼叮” “怎么了读宙?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長楔绞。 經(jīng)常有香客問我结闸,道長,這世上最難降的妖魔是什么酒朵? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任桦锄,我火速辦了婚禮,結(jié)果婚禮上蔫耽,老公的妹妹穿的比我還像新娘结耀。我一直安慰自己,他們只是感情好匙铡,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布图甜。 她就那樣靜靜地躺著,像睡著了一般慰枕。 火紅的嫁衣襯著肌膚如雪具则。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天具帮,我揣著相機(jī)與錄音博肋,去河邊找鬼。 笑死蜂厅,一個胖子當(dāng)著我的面吹牛匪凡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播掘猿,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼病游,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了稠通?” 一聲冷哼從身側(cè)響起衬衬,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎改橘,沒想到半個月后滋尉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡飞主,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年狮惜,在試婚紗的時候發(fā)現(xiàn)自己被綠了高诺。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡碾篡,死狀恐怖虱而,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情开泽,我是刑警寧澤牡拇,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站眼姐,受9級特大地震影響诅迷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜众旗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望趟畏。 院中可真熱鬧贡歧,春花似錦、人聲如沸赋秀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽猎莲。三九已至绍弟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間著洼,已是汗流浹背樟遣。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留身笤,地道東北人豹悬。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像液荸,于是被迫代替她去往敵國和親瞻佛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理娇钱,服務(wù)發(fā)現(xiàn)伤柄,斷路器,智...
    卡卡羅2017閱讀 134,695評論 18 139
  • 前言 今天是平安夜文搂,先祝大家平安夜快樂适刀。 我們之前的數(shù)十篇文章分析了 Spring 和 Mybatis 的原理,基...
    莫那一魯?shù)?/span>閱讀 14,090評論 3 31
  • 本文是我自己在秋招復(fù)習(xí)時的讀書筆記细疚,整理的知識點(diǎn)蔗彤,也是為了防止忘記川梅,尊重勞動成果,轉(zhuǎn)載注明出處哦然遏!如果你也喜歡贫途,那...
    波波波先森閱讀 12,296評論 6 86
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,844評論 6 342
  • 秋至少新紅,霜打青山悴待侵。只有相思樹永青丢早,紅豆顆顆媚。 枯葉戀枝頭秧倾,不忍隨風(fēng)墜怨酝。都道菊花插滿頭,誰懂離人淚那先。
    合肥歲月靜好閱讀 279評論 0 8