吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

spring中聲明式事務實現原理猜想

Android編程精選 ? 來源:CSDN博客 ? 作者:一擼向北 ? 2021-10-13 09:20 ? 次閱讀

@Transactional注解簡介

@Transactional是spring中聲明式事務管理的注解配置方式,相信這個注解的作用大家都很清楚。@Transactional注解可以幫助我們把事務開啟、提交或者回滾的操作,通過aop的方式進行管理。

通過@Transactional注解就能讓spring為我們管理事務,免去了重復的事務管理邏輯,減少對業務代碼的侵入,使我們開發人員能夠專注于業務層面開發。

我們知道實現@Transactional原理是基于spring aop,aop又是動態代理模式的實現,通過對源碼的閱讀,總結出下面的步驟來了解實際中,在spring 是如何利用aop來實現@Transactional的功能的。

spring中聲明式事務實現原理猜想

首先,對于spring中aop實現原理有了解的話,應該知道想要對一個方法進行代理的話,肯定需要定義切點。在@Transactional的實現中,同樣如此,spring為我們定義了以 @Transactional 注解為植入點的切點,這樣才能知道@Transactional注解標注的方法需要被代理。

有了切面定義之后,在spring的bean的初始化過程中,就需要對實例化的bean進行代理,并且生成代理對象。

生成代理對象的代理邏輯中,進行方法調用時,需要先獲取切面邏輯,@Transactional注解的切面邏輯類似于@Around,在spring中是實現一種類似代理邏輯。

@Transactional作用

根據上面的原理猜想,下面簡單介紹每個步驟的源碼以進行驗證。

首先是@Transactional,作用是定義代理植入點。我們知道代理對象創建的通過BeanPostProcessor的實現類AnnotationAwareAspectJAutoProxyCreatorpostProcessAfterInstantiation方法來實現個,如果需要進行代理,那么在這個方法就會返回一個代理對象給容器,同時判斷植入點也是在這個方法中。

那么下面開始分析,在配置好注解驅動方式的事務管理之后,spring會在ioc容器創建一個BeanFactoryTransactionAttributeSourceAdvisor實例,這個實例可以看作是一個切點,在判斷一個bean在初始化過程中是否需要創建代理對象,都需要驗證一次BeanFactoryTransactionAttributeSourceAdvisor是否是適用這個bean的切點。如果是,就需要創建代理對象,并且把BeanFactoryTransactionAttributeSourceAdvisor實例注入到代理對象中。

前文我們知道在AopUtils#findAdvisorsThatCanApply中判斷切面是否適用當前bean,可以在這個地方斷點分析調用堆棧,AopUtils#findAdvisorsThatCanApply一致調用,最終通過以下代碼判斷是否適用切點。

  • AbstractFallbackTransactionAttributeSource#computeTransactionAttribute(Method method, Class targetClass)這里可以根據參數打上條件斷點進行調試分析調用棧,targetClass就是目標class …一系列調用
  • 最終SpringTransactionAnnotationParser#parseTransactionAnnotation(java.lang.reflect.AnnotatedElement)
@Override
publicTransactionAttributeparseTransactionAnnotation(AnnotatedElementae){
//這里就是分析Method是否被@Transactional注解標注,有的話,不用說BeanFactoryTransactionAttributeSourceAdvisor適配當前bean,進行代理,并且注入切點
//BeanFactoryTransactionAttributeSourceAdvisor
AnnotationAttributesattributes=AnnotatedElementUtils.getMergedAnnotationAttributes(ae,Transactional.class);
if(attributes!=null){
returnparseTransactionAnnotation(attributes);
}
else{
returnnull;
}
}

上面就是判斷是否需要根據@Transactional進行代理對象創建的判斷過程。@Transactional的作用一個就是標識方法需要被代理,一個就是攜帶事務管理需要的一些屬性信息

動態代理邏輯實現

【aop實現原理分析】中知道,aop最終的代理對象的代理方法是

  • DynamicAdvisedInterceptor#intercept

所以我們可以在這個方法斷點分析代理邏輯。往期的面試題,點擊查看

@Override
publicObjectintercept(Objectproxy,Methodmethod,Object[]args,MethodProxymethodProxy)throwsThrowable{
ObjectoldProxy=null;
booleansetProxyContext=false;
ClasstargetClass=null;
Objecttarget=null;
try{
if(this.advised.exposeProxy){
//Makeinvocationavailableifnecessary.
oldProxy=AopContext.setCurrentProxy(proxy);
setProxyContext=true;
}
//Maybenull.Getaslateaspossibletominimizethetimewe
//"own"thetarget,incaseitcomesfromapool...
target=getTarget();
if(target!=null){
targetClass=target.getClass();
}
//follow
Listchain=this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,targetClass);
ObjectretVal;
//CheckwhetherweonlyhaveoneInvokerInterceptor:thatis,
//norealadvice,butjustreflectiveinvocationofthetarget.
if(chain.isEmpty()&&Modifier.isPublic(method.getModifiers())){
//WecanskipcreatingaMethodInvocation:justinvokethetargetdirectly.
//NotethatthefinalinvokermustbeanInvokerInterceptor,soweknow
//itdoesnothingbutareflectiveoperationonthetarget,andnohot
//swappingorfancyproxying.
Object[]argsToUse=AopProxyUtils.adaptArgumentsIfNecessary(method,args);
retVal=methodProxy.invoke(target,argsToUse);
}
else{
//Weneedtocreateamethodinvocation...
retVal=newCglibMethodInvocation(proxy,target,method,args,targetClass,chain,methodProxy).proceed();
}
retVal=processReturnType(proxy,target,method,retVal);
returnretVal;
}
finally{
if(target!=null){
releaseTarget(target);
}
if(setProxyContext){
//Restoreoldproxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}

		

通過分析List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)返回的是TransactionInterceptor,利用TransactionInterceptor是如何實現代理邏輯調用的?

跟蹤new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

發現最終是調用TransactionInterceptor#invoke方法,并且把CglibMethodInvocation注入到invoke方法中,從上面可以看到CglibMethodInvocation是包裝了目標對象的方法調用的所有必須信息,因此,在TransactionInterceptor#invoke里面也是可以調用目標方法的,并且還可以實現類似@Around的邏輯,在目標方法調用前后繼續注入一些其他邏輯,比如事務管理邏輯。

TransactionInterceptor–最終事務管理者

下面看代碼。

  • TransactionInterceptor#invoke
@Override
publicObjectinvoke(finalMethodInvocationinvocation)throwsThrowable{
//Workoutthetargetclass:maybe{@codenull}.
//TheTransactionAttributeSourceshouldbepassedthetargetclass
//aswellasthemethod,whichmaybefromaninterface.
ClasstargetClass=(invocation.getThis()!=null?AopUtils.getTargetClass(invocation.getThis()):null);

//AdapttoTransactionAspectSupport'sinvokeWithinTransaction...
returninvokeWithinTransaction(invocation.getMethod(),targetClass,newInvocationCallback(){
@Override
publicObjectproceedWithInvocation()throwsThrowable{
returninvocation.proceed();
}
});
}

繼續跟蹤invokeWithinTransaction,下面的代碼中其實就可以看出一些邏輯端倪,就是我們猜想的實現方式,事務管理。

protectedObjectinvokeWithinTransaction(Methodmethod,ClasstargetClass,finalInvocationCallbackinvocation)
throwsThrowable{

//Ifthetransactionattributeisnull,themethodisnon-transactional.
finalTransactionAttributetxAttr=getTransactionAttributeSource().getTransactionAttribute(method,targetClass);
finalPlatformTransactionManagertm=determineTransactionManager(txAttr);
finalStringjoinpointIdentification=methodIdentification(method,targetClass);

if(txAttr==null||!(tminstanceofCallbackPreferringPlatformTransactionManager)){
//StandardtransactiondemarcationwithgetTransactionandcommit/rollbackcalls.
//開啟事務
TransactionInfotxInfo=createTransactionIfNecessary(tm,txAttr,joinpointIdentification);
ObjectretVal=null;
try{
//Thisisanaroundadvice:Invokethenextinterceptorinthechain.
//Thiswillnormallyresultinatargetobjectbeinginvoked.
//方法調用
retVal=invocation.proceedWithInvocation();
}
catch(Throwableex){
//targetinvocationexception
//回滾事務
completeTransactionAfterThrowing(txInfo,ex);
throwex;
}
finally{
cleanupTransactionInfo(txInfo);
}
//提交事務
commitTransactionAfterReturning(txInfo);
returnretVal;
}

else{
//It'saCallbackPreferringPlatformTransactionManager:passaTransactionCallbackin.
try{
Objectresult=((CallbackPreferringPlatformTransactionManager)tm).execute(txAttr,
newTransactionCallback(){
@Override
publicObjectdoInTransaction(TransactionStatusstatus){
TransactionInfotxInfo=prepareTransactionInfo(tm,txAttr,joinpointIdentification,status);
try{
returninvocation.proceedWithInvocation();
}
catch(Throwableex){
if(txAttr.rollbackOn(ex)){
//ARuntimeException:willleadtoarollback.
if(exinstanceofRuntimeException){
throw(RuntimeException)ex;
}
else{
thrownewThrowableHolderException(ex);
}
}
else{
//Anormalreturnvalue:willleadtoacommit.
returnnewThrowableHolder(ex);
}
}
finally{
cleanupTransactionInfo(txInfo);
}
}
});

//Checkresult:ItmightindicateaThrowabletorethrow.
if(resultinstanceofThrowableHolder){
throw((ThrowableHolder)result).getThrowable();
}
else{
returnresult;
}
}
catch(ThrowableHolderExceptionex){
throwex.getCause();
}
}
}

		

總結

最終可以總結一下整個流程,跟開始的猜想對照。

來源:blog.csdn.net/qq_20597727/article/details/84868035

責任編輯:haq
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 代碼
    +關注

    關注

    30

    文章

    4825

    瀏覽量

    69043
  • spring
    +關注

    關注

    0

    文章

    340

    瀏覽量

    14388

原文標題:Spring的@Transactional如何實現的(必考)

文章出處:【微信號:AndroidPush,微信公眾號:Android編程精選】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    聲明資源管理方法

    1、管理k8s核心資源的三種基礎方法 陳述管理方法:主要依賴命令行CLI工具進行管理 聲明管理方法:主要依賴統一資源配置清單(manifest)進行管理 GUI管理方法:主要依賴
    的頭像 發表于 12-31 10:16 ?171次閱讀

    SSM框架的性能優化技巧 SSM框架RESTful API的實現

    : 緩存可以顯著提高系統的響應速度。 在SSM,可以使用Redis或Memcached等緩存技術來緩存頻繁訪問的數據,如數據庫查詢結果、用戶信息等。 同時,也可以利用Spring Cache抽象層來簡化
    的頭像 發表于 12-17 09:10 ?272次閱讀

    SSM框架在Java開發的應用 如何使用SSM進行web開發

    SSM框架,即Spring、SpringMVC和MyBatis的整合,是Java Web開發中常用的技術棧。它通過分層架構,實現了視圖、控制、業務邏輯和數據訪問的分離,提高了代碼的可維護性和可擴展性
    的頭像 發表于 12-16 17:28 ?649次閱讀

    Spring 應用合并之路(二):峰回路轉,柳暗花明

    提醒下,決定拋開 Spring Boot 內置的父子容器方案,完全自己實現父子容器。 如何加載 web 項目? 現在的難題只有一個:如何加載 web 項目?加載完成后,如何持續持有 web 項目?經過思考后,可以創建一個 boot 項目的
    的頭像 發表于 12-12 11:22 ?828次閱讀

    “宇宙猜想”聯合LEKEVR、有家嗨店共同打造商圈VR大空間放映廳

    空間計算內容服務商“宇宙猜想”與國內VR體驗館頭部品牌LEKEVR、有家嗨店達成戰略合作,共同打造全國商圈VR大空間放映廳。此次合作標志著VR大空間產品進一步普及化,同時也標志著“宇宙猜想”在商業體
    的頭像 發表于 12-05 16:31 ?283次閱讀
    “宇宙<b class='flag-5'>猜想</b>”聯合LEKEVR、有家嗨店共同打造商圈VR大空間放映廳

    新展來襲!《宇宙猜想·啟程》宇宙主題VR沉浸體驗展在天津博物館震撼啟幕

    11月30日,備受矚目的《宇宙猜想·啟程》——宇宙主題VR沉浸體驗展正式落地天津博物館,為觀眾帶來了一場前所未有的宇宙探索之旅。此次展覽巧妙融合了XR、空間定位等前沿技術,不僅展示了宇宙猜想
    的頭像 發表于 12-02 15:40 ?401次閱讀
    新展來襲!《宇宙<b class='flag-5'>猜想</b>·啟程》宇宙主題VR沉浸<b class='flag-5'>式</b>體驗展在天津博物館震撼啟幕

    全新NVIDIA NIM微服務實現突破性進展

    全新 NVIDIA NIM 微服務實現突破性進展,可助力氣象技術公司開發和部署 AI 模型,實現對降雪、結冰和冰雹的預測。
    的頭像 發表于 11-21 10:07 ?303次閱讀

    Spring事務實現原理

    這些操作。 spring事務有編程式事務聲明事務兩種實現
    的頭像 發表于 11-08 10:10 ?873次閱讀
    <b class='flag-5'>Spring</b><b class='flag-5'>事務實現</b>原理

    如何在反激拓撲實現軟啟動

    電子發燒友網站提供《如何在反激拓撲實現軟啟動.pdf》資料免費下載
    發表于 09-04 11:09 ?0次下載
    如何在反激<b class='flag-5'>式</b>拓撲<b class='flag-5'>中</b><b class='flag-5'>實現</b>軟啟動

    Spring Cloud Gateway網關框架

    Spring Cloud Gateway網關框架 本軟件微服務架構采用Spring Cloud Gateway網關控制框架,Spring Cloud Gateway是
    的頭像 發表于 08-22 09:58 ?545次閱讀
    <b class='flag-5'>Spring</b> Cloud Gateway網關框架

    vue+spring boot人員定位系統源碼,實現實時定位、智慧調度、軌跡追蹤

    、機具、物料上定位標簽回傳的位置信息數據,采用多維定位模式,精確定位人、機具、物料的實時位置,實現實時定位、物料標簽配置、智慧調度、軌跡追蹤、工時統計、區域物料統計、電子圍欄等應用功能。 技術架構:java+ spring boot+ v
    的頭像 發表于 08-08 14:27 ?858次閱讀
    vue+<b class='flag-5'>spring</b> boot人員定位系統源碼,<b class='flag-5'>實現</b>實時定位、智慧調度、軌跡追蹤

    鴻蒙開發Ability Kit程序框架服務:聲明權限

    應用在申請權限時,需要在項目的配置文件,逐個聲明需要的權限,否則應用將無法獲取授權。
    的頭像 發表于 07-01 09:22 ?393次閱讀
    鴻蒙開發Ability Kit程序框架服務:<b class='flag-5'>聲明</b>權限

    玩轉Spring狀態機

    說起Spring狀態機,大家很容易聯想到這個狀態機和設計模式狀態模式的區別是啥呢?沒錯,Spring狀態機就是狀態模式的一種實現,在介紹Sprin
    的頭像 發表于 06-25 14:21 ?1030次閱讀
    玩轉<b class='flag-5'>Spring</b>狀態機

    庫克稱中國內地iPhone業務實際上實現增長

    蘋果公司首席執行官蒂姆·庫克(Tim Cook)近日表示,盡管大中華區截至3月份財季的整體收入有所下滑,但中國內地市場的iPhone業務實際上實現了增長,且降幅低于預期。這一積極信號顯示了中國市場對于蘋果產品的強勁需求。
    的頭像 發表于 05-09 09:40 ?353次閱讀

    芯寧波嚴正聲明!絕不諒解

    來源:國芯網,謝謝 編輯:感知芯視界 2月20日,芯寧波發布官方聲明,不與公司前董事兼總經理黃河、前財務負責人王瀛進行任何和解或諒解! 上述二人因涉嫌挪用資金罪于2023年11月14日被寧波市
    的頭像 發表于 02-21 09:59 ?636次閱讀
    百家乐官网投注网出租| 百家乐投注方式| 百家乐官网公式书| 玉田县| 大发888常见断续| 狮威百家乐赌场娱乐网规则| 百家乐官网园有限公司| 百家乐官网博娱乐场开户注册| 百家乐官网三跳| 金冠百家乐官网娱乐城| 柳河县| 香港六合彩开奖现场直播| 新锦江百家乐官网娱乐场开户注册| 太阳城百家乐官网群| 永利娱乐| 威尼斯人娱乐城排名| 博彩网百家乐全讯网| 百家乐网投打法| 百家乐天天乐娱乐场| 百家乐大小是什么| 宾利百家乐游戏| 24山风水实例| 三元玄空24山坐向开门| 百家乐官网园qq群| 沙龙百家乐官网代理| 百家乐官网导航| 百家乐官网视频游戏大厅| 百家乐官网真人游戏网上投注| 真人百家乐官网代理合作| 百家乐官网最新庄闲投注法| 太阳城百家乐官网看牌| 下载百家乐官网棋牌大厅| 百家乐官网偷吗| 花莲县| 香港六合彩报码室| 舟山星空棋牌下载| 香港六合彩特码| 和记网上娱乐| 网上真钱赌博网站| 铁岭县| 黎平县|