在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

淺談Spring事務(wù)底層原理

jf_ro2CN3Fa ? 來源:CSDN技術(shù)社區(qū) ? 作者:蕭炎 ? 2022-12-06 09:56 ? 次閱讀

一、@EnableTransactionManagement工作原理

開啟Spring事務(wù)本質(zhì)上就是增加了一個(gè)Advisor,但我們使用@EnableTransactionManagement注解來開啟Spring事務(wù)是,該注解代理的功能就是向Spring容器中添加了兩個(gè)Bean:

AutoProxyRegistrar

ProxyTransactionManagementConfiguration

AutoProxyRegistrar主要的作用是向Spring容器中注冊(cè)了一個(gè)InfrastructureAdvisorAutoProxyCreator的Bean。而InfrastructureAdvisorAutoProxyCreator繼承了AbstractAdvisorAutoProxyCreator,所以這個(gè)類的主要作用就是開啟自動(dòng)代理的作用,也就是一個(gè)BeanPostProcessor,會(huì)在初始化后步驟中去尋找Advisor類型的Bean,并判斷當(dāng)前某個(gè)Bean是否有匹配的Advisor,是否需要利用動(dòng)態(tài)代理產(chǎn)生一個(gè)代理對(duì)象。

ProxyTransactionManagementConfiguration是一個(gè)配置類,它又定義了另外三個(gè)bean:

BeanFactoryTransactionAttributeSourceAdvisor :一個(gè)Advisor

AnnotationTransactionAttributeSource :相當(dāng)于BeanFactoryTransactionAttributeSourceAdvisor中的Pointcut

TransactionInterceptor :相當(dāng)于BeanFactoryTransactionAttributeSourceAdvisor中的Advice

AnnotationTransactionAttributeSource就是用來判斷某個(gè)類上是否存在@Transactional注解,或者判斷某個(gè)方法上是否存在@Transactional注解的。

TransactionInterceptor就是代理邏輯,當(dāng)某個(gè)類中存在@Transactional注解時(shí),到時(shí)就產(chǎn)生一個(gè)代理對(duì)象作為Bean,代理對(duì)象在執(zhí)行某個(gè)方法時(shí),最終就會(huì)進(jìn)入到TransactionInterceptor的invoke()方法。

基于 Spring Boot + MyBatis Plus + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

項(xiàng)目地址:https://github.com/YunaiV/ruoyi-vue-pro

視頻教程:https://doc.iocoder.cn/video/

二、Spring事務(wù)基本執(zhí)行原理

一個(gè)Bean在執(zhí)行Bean的創(chuàng)建生命周期時(shí),會(huì)經(jīng)過InfrastructureAdvisorAutoProxyCreator的初始化后的方法,會(huì)判斷當(dāng)前Bean對(duì)象是否和BeanFactoryTransactionAttributeSourceAdvisor匹配,匹配邏輯為判斷該Bean的類上是否存在@Transactional注解,或者類中的某個(gè)方法上是否存在@Transactional注解,如果存在則表示該Bean需要進(jìn)行動(dòng)態(tài)代理產(chǎn)生一個(gè)代理對(duì)象作為Bean對(duì)象。

該代理對(duì)象在執(zhí)行某個(gè)方法時(shí),會(huì)再次判斷當(dāng)前執(zhí)行的方法是否和BeanFactoryTransactionAttributeSourceAdvisor匹配,如果匹配則執(zhí)行該Advisor中的TransactionInterceptor的invoke()方法,執(zhí)行基本流程為:

利用所配置的PlatformTransactionManager事務(wù)管理器新建一個(gè)數(shù)據(jù)庫連接

修改數(shù)據(jù)庫連接的autocommit為false

執(zhí)行MethodInvocation.proceed()方法,簡(jiǎn)單理解就是執(zhí)行業(yè)務(wù)方法,其中就會(huì)執(zhí)行sql

如果沒有拋異常,則提交

如果拋了異常,則回滾

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

項(xiàng)目地址:https://github.com/YunaiV/yudao-cloud

視頻教程:https://doc.iocoder.cn/video/

三、Spring事務(wù)詳細(xì)執(zhí)行流程

Spring事務(wù)執(zhí)行流程圖:https://www.processon.com/view/link/5fab6edf1e0853569633cc06

f410b84e-7490-11ed-8abf-dac502259ad0.png

四、Spring事務(wù)傳播機(jī)制

在開發(fā)過程中,經(jīng)常會(huì)出現(xiàn)一個(gè)方法調(diào)用另外一個(gè)方法,那么這里就涉及到了多種場(chǎng)景,比如a()調(diào)用b():

a()和b()方法中的所有sql需要在同一個(gè)事務(wù)中嗎?

a()和b()方法需要單獨(dú)的事務(wù)嗎?

a()需要在事務(wù)中執(zhí)行,b()還需要在事務(wù)中執(zhí)行嗎?

等等情況…

所以,這就要求Spring事務(wù)能支持上面各種場(chǎng)景,這就是Spring事務(wù)傳播機(jī)制的由來。那Spring事務(wù)傳播機(jī)制是如何實(shí)現(xiàn)的呢?

先來看上述幾種場(chǎng)景中的一種情況,a()在一個(gè)事務(wù)中執(zhí)行,調(diào)用b()方法時(shí)需要新開一個(gè)事務(wù)執(zhí)行:

首先,代理對(duì)象執(zhí)行a()方法前,先利用事務(wù)管理器新建一個(gè)數(shù)據(jù)庫連接a

將數(shù)據(jù)庫連接a的autocommit改為false

把數(shù)據(jù)庫連接a設(shè)置到ThreadLocal中

執(zhí)行a()方法中的sql

執(zhí)行a()方法過程中,調(diào)用了b()方法(注意用代理對(duì)象調(diào)用b()方法)

代理對(duì)象執(zhí)行b()方法前,判斷出來了當(dāng)前線程中已經(jīng)存在一個(gè)數(shù)據(jù)庫連接a了,表示當(dāng)前線程其實(shí)已經(jīng)擁有一個(gè)Spring事務(wù)了,則進(jìn)行掛起

掛起就是把ThreadLocal中的數(shù)據(jù)庫連接a從ThreadLocal中移除,并放入一個(gè)掛起資源對(duì)象中

掛起完成后,再次利用事務(wù)管理器新建一個(gè)數(shù)據(jù)庫連接b

將數(shù)據(jù)庫連接b的autocommit改為false

把數(shù)據(jù)庫連接b設(shè)置到ThreadLocal中

執(zhí)行b()方法中的sql

b()方法正常執(zhí)行完,則從ThreadLocal中拿到數(shù)據(jù)庫連接b進(jìn)行提交

提交之后會(huì)恢復(fù)所掛起的數(shù)據(jù)庫連接a,這里的恢復(fù),其實(shí)只是把在掛起資源對(duì)象中所保存的數(shù)據(jù)庫連接a再次設(shè)置到ThreadLocal中

a()方法正常執(zhí)行完,則從ThreadLocal中拿到數(shù)據(jù)庫連接a進(jìn)行提交

這個(gè)過程中最為核心的是:在執(zhí)行某個(gè)方法時(shí),判斷當(dāng)前是否已經(jīng)存在一個(gè)事務(wù),就是判斷當(dāng)前線程的ThreadLocal中是否存在一個(gè)數(shù)據(jù)庫連接對(duì)象,如果存在則表示已經(jīng)存在一個(gè)事務(wù)了。

五、Spring事務(wù)傳播機(jī)制分類

其中,以非事務(wù)方式運(yùn)行,表示以非Spring事務(wù)運(yùn)行,表示在執(zhí)行這個(gè)方法時(shí),Spring事務(wù)管理器不會(huì)去建立數(shù)據(jù)庫連接,執(zhí)行sql時(shí),由Mybatis或JdbcTemplate自己來建立數(shù)據(jù)庫連接來執(zhí)行sql。

案例分析

情況1

@Component
publicclassUserService{
@Autowired
privateUserServiceuserService;

@Transactional
publicvoidtest(){
//test方法中的sql
userService.a();
}

@Transactional
publicvoida(){
//a方法中的sql
}
}

默認(rèn)情況下傳播機(jī)制為REQUIRED,表示當(dāng)前如果沒有事務(wù)則新建一個(gè)事務(wù),如果有事務(wù)則在當(dāng)前事務(wù)中執(zhí)行。

所以上面這種情況的執(zhí)行流程如下:

新建一個(gè)數(shù)據(jù)庫連接conn

設(shè)置conn的autocommit為false

執(zhí)行test方法中的sql

執(zhí)行a方法中的sql

執(zhí)行conn的commit()方法進(jìn)行提交

情況2

假如是這種情況:

@Component
publicclassUserService{
@Autowired
privateUserServiceuserService;

@Transactional
publicvoidtest(){
//test方法中的sql
userService.a();
intresult=100/0;
}

@Transactional
publicvoida(){
//a方法中的sql
}
}

所以上面這種情況的執(zhí)行流程如下:

新建一個(gè)數(shù)據(jù)庫連接conn

設(shè)置conn的autocommit為false

執(zhí)行test方法中的sql

執(zhí)行a方法中的sql

拋出異常

執(zhí)行conn的rollback()方法進(jìn)行回滾,所以兩個(gè)方法中的sql都會(huì)回滾掉

情況3

假如是這種情況:

@Component
publicclassUserService{
@Autowired
privateUserServiceuserService;

@Transactional
publicvoidtest(){
//test方法中的sql
userService.a();
}

@Transactional
publicvoida(){
//a方法中的sql
intresult=100/0;
}
}

所以上面這種情況的執(zhí)行流程如下:

新建一個(gè)數(shù)據(jù)庫連接conn

設(shè)置conn的autocommit為false

執(zhí)行test方法中的sql

執(zhí)行a方法中的sql

拋出異常

執(zhí)行conn的rollback()方法進(jìn)行回滾,所以兩個(gè)方法中的sql都會(huì)回滾掉

情況4

如果是這種情況:

@Component
publicclassUserService{
@Autowired
privateUserServiceuserService;

@Transactional
publicvoidtest(){
//test方法中的sql
userService.a();
}

@Transactional(propagation=Propagation.REQUIRES_NEW)
publicvoida(){
//a方法中的sql
intresult=100/0;
}
}

所以上面這種情況的執(zhí)行流程如下:

新建一個(gè)數(shù)據(jù)庫連接conn

設(shè)置conn的autocommit為false

執(zhí)行test方法中的sql

又新建一個(gè)數(shù)據(jù)庫連接conn2

執(zhí)行a方法中的sql

拋出異常

執(zhí)行conn2的rollback()方法進(jìn)行回滾

繼續(xù)拋異常,對(duì)于test()方法而言,它會(huì)接收到一個(gè)異常,然后拋出

執(zhí)行conn的rollback()方法進(jìn)行回滾,最終還是兩個(gè)方法中的sql都回滾了

六、Spring事務(wù)強(qiáng)制回滾

正常情況下,a()調(diào)用b()方法時(shí),如果b()方法拋了異常,但是在a()方法捕獲了,那么a()的事務(wù)還是會(huì)正常提交的,但是有的時(shí)候,我們捕獲異常可能僅僅只是不把異常信息返回給客戶端,而是為了返回一些更友好的錯(cuò)誤信息,而這個(gè)時(shí)候,我們還是希望事務(wù)能回滾的,那這個(gè)時(shí)候就得告訴Spring把當(dāng)前事務(wù)回滾掉,做法就是:

@Transactional
publicvoidtest(){

//執(zhí)行sql
try{
b();
}catch(Exceptione){
//構(gòu)造友好的錯(cuò)誤信息返回
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}

}

publicvoidb()throwsException{
thrownewException();
}

七、TransactionSynchronization

Spring事務(wù)有可能會(huì)提交,回滾、掛起、恢復(fù),所以Spring事務(wù)提供了一種機(jī)制,可以讓程序員來監(jiān)聽當(dāng)前Spring事務(wù)所處于的狀態(tài)。

@Component
publicclassUserService{

@Autowired
privateJdbcTemplatejdbcTemplate;

@Autowired
privateUserServiceuserService;

@Transactional
publicvoidtest(){
TransactionSynchronizationManager.registerSynchronization(newTransactionSynchronization(){

@Override
publicvoidsuspend(){
System.out.println("test被掛起了");
}

@Override
publicvoidresume(){
System.out.println("test被恢復(fù)了");
}

@Override
publicvoidbeforeCommit(booleanreadOnly){
System.out.println("test準(zhǔn)備要提交了");
}

@Override
publicvoidbeforeCompletion(){
System.out.println("test準(zhǔn)備要提交或回滾了");
}

@Override
publicvoidafterCommit(){
System.out.println("test提交成功了");
}

@Override
publicvoidafterCompletion(intstatus){
System.out.println("test提交或回滾成功了");
}
});

jdbcTemplate.execute("insertintot1values(1,1,1,1,'1')");
System.out.println("test");
userService.a();
}

@Transactional(propagation=Propagation.REQUIRES_NEW)
publicvoida(){
TransactionSynchronizationManager.registerSynchronization(newTransactionSynchronization(){

@Override
publicvoidsuspend(){
System.out.println("a被掛起了");
}

@Override
publicvoidresume(){
System.out.println("a被恢復(fù)了");
}

@Override
publicvoidbeforeCommit(booleanreadOnly){
System.out.println("a準(zhǔn)備要提交了");
}

@Override
publicvoidbeforeCompletion(){
System.out.println("a準(zhǔn)備要提交或回滾了");
}

@Override
publicvoidafterCommit(){
System.out.println("a提交成功了");
}

@Override
publicvoidafterCompletion(intstatus){
System.out.println("a提交或回滾成功了");
}
});

jdbcTemplate.execute("insertintot1values(2,2,2,2,'2')");
System.out.println("a");
}

}

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 容器
    +關(guān)注

    關(guān)注

    0

    文章

    495

    瀏覽量

    22061
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    340

    瀏覽量

    14343

原文標(biāo)題:淺談 Spring 事務(wù)底層原理

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Spring事務(wù)失效的十種常見場(chǎng)景

    Spring針對(duì)Java Transaction API (JTA)、JDBC、Hibernate和Java Persistence API(JPA)等事務(wù) API,實(shí)現(xiàn)了一致的編程模型,而
    的頭像 發(fā)表于 12-11 15:03 ?914次閱讀

    Spring事務(wù)實(shí)現(xiàn)原理

    作者:京東零售 范錫軍 1、引言 springspring-tx模塊提供了對(duì)事務(wù)管理支持,使用spring事務(wù)可以讓我們從復(fù)雜的
    的頭像 發(fā)表于 11-08 10:10 ?824次閱讀
    <b class='flag-5'>Spring</b><b class='flag-5'>事務(wù)</b>實(shí)現(xiàn)原理

    什么是java spring

    。在SSH項(xiàng)目中管理事務(wù)以及對(duì)象的注入Spring是非侵入式的:基于Spring開發(fā)的系統(tǒng)中的對(duì)象一般不依賴于Spring的類。組成 Spring
    發(fā)表于 09-11 11:16

    Spring的兩種方式事務(wù)管理和API接口介紹

    Spring事務(wù)管理
    發(fā)表于 03-21 06:52

    Spring事務(wù)分析的實(shí)現(xiàn)方式

    Spring事務(wù)原理分析
    發(fā)表于 07-02 15:19

    詳解Spring事務(wù)管理

    在學(xué)習(xí)spring事務(wù)管理時(shí),我忍不住要問,spring為什么進(jìn)行事務(wù)管理,spring怎么進(jìn)行的事務(wù)
    發(fā)表于 07-12 06:54

    Spring事務(wù)管理詳解說明

    Spring事務(wù)管理詳解
    發(fā)表于 05-20 13:46

    spring中聲明式事務(wù)實(shí)現(xiàn)原理猜想

    ? @Transactional注解簡(jiǎn)介 @Transactional 是spring中聲明式事務(wù)管理的注解配置方式,相信這個(gè)注解的作用大家都很清楚。 @Transactional 注解可以幫助
    的頭像 發(fā)表于 10-13 09:20 ?1630次閱讀

    Spring認(rèn)證是什么?

    ,例如:配置、組件掃描、AOP、數(shù)據(jù)訪問和事務(wù)、REST、安全、自動(dòng)配置、執(zhí)行器、 Spring boot測(cè)試等。
    的頭像 發(fā)表于 07-04 10:19 ?1317次閱讀
    <b class='flag-5'>Spring</b>認(rèn)證是什么?

    淺談Spring事務(wù)的那些坑

    對(duì)于從事java開發(fā)工作的同學(xué)來說,spring事務(wù)肯定再熟悉不過了。在某些業(yè)務(wù)場(chǎng)景下,如果同時(shí)有多張表的寫入操作,為了保證操作的原子性(要么同時(shí)成功,要么同時(shí)失敗)避免數(shù)據(jù)不一致的情況,我們一般都會(huì)使用spring
    的頭像 發(fā)表于 10-11 10:31 ?751次閱讀

    發(fā)現(xiàn)一個(gè)Spring事務(wù)的巨坑bug 你必須要小心了

    1.錯(cuò)誤的訪問權(quán)限 2.方法被定義成final的 3.方法內(nèi)部調(diào)用 4.當(dāng)前實(shí)體沒有被spring管理 5.錯(cuò)誤的spring事務(wù)傳播特性 6.數(shù)據(jù)庫不支持事務(wù) 7.自己吞掉了異常 8
    的頭像 發(fā)表于 10-11 18:17 ?855次閱讀

    Spring事務(wù)在哪幾種情況下會(huì)不生效?

    日常開發(fā)中,我們經(jīng)常使用到spring事務(wù)。最近星球一位還有去美團(tuán)面試,被問了這么一道面試題: Spring 事務(wù)在哪幾種情況下會(huì)不生效?
    的頭像 發(fā)表于 05-10 17:53 ?934次閱讀
    <b class='flag-5'>Spring</b><b class='flag-5'>事務(wù)</b>在哪幾種情況下會(huì)不生效?

    8個(gè)Spring事務(wù)失效的場(chǎng)景介紹

    作為Java開發(fā)工程師,相信大家對(duì)Spring事務(wù)的使用并不陌生。但是你可能只是停留在基礎(chǔ)的使用層面上,在遇到一些比較特殊的場(chǎng)景,事務(wù)可能沒有生效,直接在生產(chǎn)上暴露了,這可能就會(huì)導(dǎo)致比較嚴(yán)重的生產(chǎn)
    的頭像 發(fā)表于 05-11 10:41 ?674次閱讀
    8個(gè)<b class='flag-5'>Spring</b><b class='flag-5'>事務(wù)</b>失效的場(chǎng)景介紹

    spring事務(wù)失效的一些場(chǎng)景

    對(duì)于從事java開發(fā)工作的同學(xué)來說,spring事務(wù)肯定再熟悉不過了。 在某些業(yè)務(wù)場(chǎng)景下,如果一個(gè)請(qǐng)求中,需要同時(shí)寫入多張表的數(shù)據(jù)。為了保證操作的原子性(要么同時(shí)成功,要么同時(shí)失敗),避免數(shù)據(jù)
    的頭像 發(fā)表于 10-08 14:27 ?447次閱讀
    <b class='flag-5'>spring</b><b class='flag-5'>事務(wù)</b>失效的一些場(chǎng)景

    Spring事務(wù)傳播性的相關(guān)知識(shí)

    本文主要介紹了Spring事務(wù)傳播性的相關(guān)知識(shí)。
    的頭像 發(fā)表于 01-10 09:29 ?447次閱讀
    <b class='flag-5'>Spring</b><b class='flag-5'>事務(wù)</b>傳播性的相關(guān)知識(shí)
    主站蜘蛛池模板: 怡红院色视频在线| 色多多影视| 欧美一级一一特黄| 成人99国产精品| 国产精品久久久久影院免费| 天天添天天射| 狠狠操天天干| 国产婷婷| 久久不射影院| 午夜视频入口| 69中国xxxxxxxx18| 日本三级日产三级国产三级| 狠狠色丁香久久婷婷| 97影院理论| 久久天天干| 中文字幕欧美成人免费| 色播图片| 亚洲第一在线视频| 性做久久久久| 色噜噜狠狠成人影院| 韩国免费特一级毛片| 五月天婷婷在线免费观看 | 亚洲婷婷综合色高清在线| 日本www高清| 日本加勒比视频在线观看| 国产成人高清精品免费5388密| 久久成人综合| 1024手机免费看片| 色老头网站久久网| 人日人操| 亚欧成人乱码一区二区| 在线观看黄日本高清视频| 视频一区视频二区在线观看| 久久综合九色综合网站| 国产精品久久久亚洲456| 色宅男| 国产黄色大片又色又爽| 精品亚洲大全| 四虎影院永久在线| chinese国产videoxx实拍| 亚洲91色|