日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring中解决事务以及异步注解失效

發(fā)布時(shí)間:2025/3/15 javascript 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring中解决事务以及异步注解失效 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Spring中解決事務(wù)以及異步注解失效

一、重現(xiàn)@Transaction失效的場(chǎng)景

? ? ? ? 有如下業(yè)務(wù)場(chǎng)景,新增訂單后,自動(dòng)發(fā)送短信,下面的代碼在同一個(gè)類中:

@Transaction

public void addOrder(OrderInfo? orderInfo){?

? ? ? ? orderMapper.insert(orderInfo);

? ? ? ? try{

? ? ? ? ? ? ? ? sendMesg(orderInfo?);

? ? ? ? }cach(Exception e){

? ? ? ? ? ? ? ? e.printStrace();

????????}

}

@Transaction

public void sendMesg(?OrderInfo? orderInfo?){

? ? ? ? mesgMapper.insert(orderInfo?);

? ? ? ? throws new RuntimeException("發(fā)送短信出現(xiàn)異常!");

}

? ? ? ? 上面的偽代碼模擬新增訂單后,自動(dòng)發(fā)送短信的業(yè)務(wù)場(chǎng)景。兩個(gè)操作被標(biāo)識(shí)為事務(wù),為了不影響發(fā)送短信出現(xiàn)異常影響訂單的插入,在調(diào)用發(fā)送短信的方法時(shí),通過 try....cach...捕獲其異常并處理,不影響訂單表的插入。

? ? ? ? 因?yàn)閟endMesg標(biāo)識(shí)為事務(wù),其拋出異常后,事務(wù)按正常邏輯來說,事務(wù)會(huì)進(jìn)行回滾,即短信表中不會(huì)插入記錄。然而事與愿違,出現(xiàn)的結(jié)果是短信表也插入了記錄。

二、重現(xiàn)異步注解失效的場(chǎng)景

1、異步注解@Async介紹

? ? ? ? 基于@Async標(biāo)注的方法,稱之為異步方法,這些方法在執(zhí)行的時(shí)候,spring將會(huì)為其開辟獨(dú)立的線程執(zhí)行,調(diào)用者無需等待它的完成,即可繼續(xù)其他的操作。

2、如何使用@Async

? ? ? ? 增加 aspectj 相關(guān)的依賴;

? ? ? ? 修改 spring配置文件,在配置文件中增加如下配置:

? ? ? ? <task:annotation-driven executor = "annotationExecutor"? />

? ? ? ? <task:executor id="annotationExecutor" pool-size="20" />

? ? ? ? 在方法上加上@Async注解。

3、業(yè)務(wù)場(chǎng)景介紹

預(yù)定旅游套餐業(yè)務(wù)場(chǎng)景

@Transaction?

public void planTourismPackages(Order orderInfo){

? ? ? ? dealPassengerTicketBusiness(orderInfo);

? ? ? ? dealHotelBusiness(orderInfo);

? ? ? ? sendMesg(orderInfo);

? ? ? ? sendEmial(orderInfo);

?}

@Async

public void sendMesg(?OrderInfo? orderInfo?){

? ??????mesgMapper.insert(?orderInfo??);? ? ? ? ?

? ??????throws new RuntimeException("發(fā)送短信出現(xiàn)異常!");?

}

? ? ? ? 預(yù)定旅游套餐時(shí),首先處理機(jī)票預(yù)定業(yè)務(wù),然后處理酒店預(yù)定業(yè)務(wù),最后發(fā)送短信和郵件。發(fā)送短信和郵件屬于輔助業(yè)務(wù),可以讓其異步執(zhí)行,所以在方法上加了@Async注解,讓其異步執(zhí)行。為了演示效果,我將planTourismPackages方法標(biāo)識(shí)為事務(wù)處理,故意讓sendMesg方法拋出異常。按我們預(yù)想,因?yàn)閟endMesg方法異步執(zhí)行,其拋出異常應(yīng)該不會(huì)影響planTourismPackages事務(wù)的提交,機(jī)票預(yù)定表和酒店預(yù)定表應(yīng)該會(huì)插入記錄。但是,事與愿違,sendMesg拋出異常導(dǎo)致planTourismPackages事務(wù)會(huì)滾了,說明@Async并未生效。

三、原因分析

? ? ? ? 為什么會(huì)出現(xiàn)上面的事務(wù)和異步注解失效呢?

? ? ? ? spring聲明式事務(wù)和異步注解的實(shí)現(xiàn)都是基于spring aop,即對(duì)標(biāo)識(shí)的方法進(jìn)行增強(qiáng)。spring aop的底層實(shí)現(xiàn)原理是 jdk 動(dòng)態(tài)代理。因?yàn)槭聞?wù)注解方法,異步方法的調(diào)用的方法在同一個(gè)類中,所以發(fā)送短信方法是在調(diào)用方法的代理對(duì)象中執(zhí)行的,沒有對(duì)發(fā)送短信方法進(jìn)行增強(qiáng)。如下圖:

orderMapper.insert(?orderInfo?);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

try{?

? ? ? ? ?this.sendMesg(?orderInfo??);?

?}cach(Exception e){?

? ??????e.printStrace(); ??

?}?

public void planTourismPackages(Order orderInfo){? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

????????dealHotelBusiness(?orderInfo?);?

????????dealPassengerTicketBusiness(?orderInfo?);??

????????this.sendMesg(?orderInfo?);

????????this.sendEmial(?orderInfo?);??

}

四、解決方案

? ? ? ? 要解決上面的問題,必須要實(shí)現(xiàn)發(fā)送短信方法的增強(qiáng),使其能夠成為事務(wù)或者異步方法,即讓代理生效。spring的解決方案如下:

? ? ? ? 1、在spring配置文件xml新增如下語句:

? ? ? ? 先開啟cglib代理,開啟 exposeProxy=true,暴露代理對(duì)象

? ? ? ? <aop:aspectj-autoproxy expose-proxy="true"/>

? ? ? ? 2、使用AopContext 獲取當(dāng)前對(duì)象的動(dòng)態(tài)代理。

? ? ? ? 修改配置文件后,代碼修改,用獲取到的動(dòng)態(tài)代理去執(zhí)行發(fā)送短信方法,如下:

? ? ? ? TourServer currentProxy = (TourServer?)AopContext.currentProxy();

? ??????currentProxy.sendMesg(orderInfo);

? ??????currentProxy.sendEmail(orderInfo);

總結(jié)

以上是生活随笔為你收集整理的Spring中解决事务以及异步注解失效的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。