亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring底層事務(wù)原理解析

 更新時間:2022年12月10日 11:47:18   作者:填丶涂  
Spring事務(wù)有可能會提交,回滾、掛起、恢復(fù),所以Spring事務(wù)提供了一種機制,可以讓程序員來監(jiān)聽當(dāng)前Spring事務(wù)所處于的狀態(tài),這篇文章主要介紹了Spring底層事務(wù)原理,需要的朋友可以參考下

一、@EnableTransactionManagement工作原理

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

(1)AutoProxyRegistrar
(2)ProxyTransactionManagementConfiguration

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

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

bean定義
BeanFactoryTransactionAttributeSourceAdvisor一個Advisor。
AnnotationTransactionAttributeSource相當(dāng)于BeanFactoryTransactionAttributeSourceAdvisor中的Pointcut。就是用來判斷某個類上是否存在@Transactional注解,或者判斷某個方法上是否存在@Transactional注解的。
TransactionInterceptor相當(dāng)于BeanFactoryTransactionAttributeSourceAdvisor中的Advice;就是代理邏輯,當(dāng)某個類中存在@Transactional注解時,到時就產(chǎn)生一個代理對象作為Bean,代理對象在執(zhí)行某個方法時,最終就會進入到TransactionInterceptor的invoke()方法。。

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

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

利用所配置的PlatformTransactionManager事務(wù)管理器新建一個數(shù)據(jù)庫連接修改數(shù)據(jù)庫連接的autocommit為false執(zhí)行MethodInvocation.proceed()方法,簡單理解就是執(zhí)行業(yè)務(wù)方法,其中就會執(zhí)行sql如果沒有拋異常,則提交如果拋了異常,則回滾 三、Spring事務(wù)的過程

1、數(shù)據(jù)庫:建立連接、開啟事務(wù)、進行sql操作、成功提交、失敗回滾
2、業(yè)務(wù)邏輯:準備工作(可以進行前置通知)、開啟事務(wù)、事務(wù)操作、成功提交(可以后置通知)、失敗回滾(異常通知)
spring的事務(wù)是由aop實現(xiàn)的,首先要生成具體的代理對象,然后按照aop流程執(zhí)行具體
的操作邏輯,正常情況下要通過通知來完成核心功能,但是事務(wù)部署通過通知來實現(xiàn)的,
而是通過TransactionInterceptor來實現(xiàn)的,然后調(diào)用invoke來實現(xiàn)具體的邏輯。
步驟如下:
1、先做準備工作,解析各個方法上事務(wù)相關(guān)的屬性,根據(jù)具體的屬性來判斷是否開始新事務(wù)。

2、當(dāng)需要開啟的時候獲取數(shù)據(jù)庫連接,關(guān)閉自動提交功能,開啟事務(wù)。

3、執(zhí)行具體的sql邏輯操作,在操作的過程中如果執(zhí)行失敗會通過 completeTransactionafterthrowing來完成事務(wù)的回滾操作,回滾的
具體邏輯是通過dorollback方法實現(xiàn),實現(xiàn)時也要先獲取連接對象,
然后通過連接對象進行回滾(conn.rollback)。

4、如果執(zhí)行成功,那么通過completeTransactionafterrunning來完成事務(wù)的提交操作,
具體邏輯是通過docommit方法來實現(xiàn),實現(xiàn)的時候也是先獲取連接,通過連接對象來
進行提交(conn.commit)。

5、最后事務(wù)執(zhí)行完畢需要清除事務(wù)相關(guān)的事務(wù)信息(cleanupTransactioninfo)。

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

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

a()和b()方法中的所有sql需要在同一個事務(wù)中嗎?a()和b()方法中的所有sql需要在同一個事務(wù)中嗎?a()需要在事務(wù)中執(zhí)行,b()還需要在事務(wù)中執(zhí)行嗎?或者其他情況
這種情況下就要求Spring事務(wù)能支持上面各種場景,這就是Spring事務(wù)傳播機制的由來。
那Spring事務(wù)傳播機制是如何實現(xiàn)的呢?

先描述其中一個場景中情況,a()在一個事務(wù)中執(zhí)行,調(diào)用b()方法時需要新開一個事務(wù)執(zhí)行:

代理對象執(zhí)行a()方法前,先利用事務(wù)管理器新建一個數(shù)據(jù)庫連接a將數(shù)據(jù)庫連接a的autocommit改為false把數(shù)據(jù)庫連接a設(shè)置到ThreadLocal中執(zhí)行a()方法中的sql執(zhí)行a()方法過程中,調(diào)用了b()方法(注意用代理對象調(diào)用b()方法)a()方法正常執(zhí)行完,則從ThreadLocal中拿到數(shù)據(jù)庫連接a進行提交

關(guān)于步驟5的一些詳細解釋:
1、代理對象執(zhí)行b()方法前,判斷出來了當(dāng)前線程中已經(jīng)存在一個數(shù)據(jù)庫連接a了,表示當(dāng)前線程其實已經(jīng)擁有一個Spring事務(wù)了,則進行掛起
2、掛起就是把ThreadLocal中的數(shù)據(jù)庫連接a從ThreadLocal中移除,并放入一個掛起資源對象中
3、掛起完成后,再次利用事務(wù)管理器新建一個數(shù)據(jù)庫連接b
4、將數(shù)據(jù)庫連接b的autocommit改為false
5、把數(shù)據(jù)庫連接b設(shè)置到ThreadLocal中
6、執(zhí)行b()方法中的sql
7、b()方法正常執(zhí)行完,則從ThreadLocal中拿到數(shù)據(jù)庫連接b進行提交
8、提交之后會恢復(fù)所掛起的數(shù)據(jù)庫連接a,這里的恢復(fù),其實只是把在掛起資源對象中所保存的數(shù)據(jù)庫連接a再次設(shè)置到ThreadLocal中

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

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

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

(1)案例分析、情況1

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

@Component
public class UserService {
 	@Autowired
 	private UserService userService;

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

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

所以情況1的執(zhí)行流程如下:

1、新建一個數(shù)據(jù)庫連接conn
2、設(shè)置conn的autocommit為false
3、執(zhí)行test方法中的sql
4、執(zhí)行a方法中的sql
5、執(zhí)行conn的commit()方法進行提交

(2)案例分析、情況2

如果是這種情況:

@Component
public class UserService {
 	@Autowired
 	private UserService userService;

 	@Transactional
 	public void test() {
  		// test方法中的sql
  		userService.a();
        int result = 100/0;
 	}

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

所以情況2的執(zhí)行流程如下:

1、新建一個數(shù)據(jù)庫連接conn
2、設(shè)置conn的autocommit為false
3、執(zhí)行test方法中的sql
4、執(zhí)行a方法中的sql
5、拋出異常
6、執(zhí)行conn的rollback()方法進行回滾,所以兩個方法中的sql都會回滾掉

(3)案例分析、情況3

@Component
public class UserService {
 	@Autowired
 	private UserService userService;

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

 	@Transactional
 	public void a() {
  		// a方法中的sql
        int result = 100/0;
 	}
}

所以情況3的執(zhí)行流程如下:

1、新建一個數(shù)據(jù)庫連接conn
2、設(shè)置conn的autocommit為false
3、執(zhí)行test方法中的sql
4、執(zhí)行a方法中的sql
5、拋出異常
6、執(zhí)行conn的rollback()方法進行回滾,所以兩個方法中的sql都會回滾掉

(4)案例分析、情況4

@Component
public class UserService {
 	@Autowired
 	private UserService userService;

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

 	@Transactional(propagation = Propagation.REQUIRES_NEW)
 	public void a() {
  		// a方法中的sql
  		int result = 100/0;
 	}
}

所以情況3的執(zhí)行流程如下:

1、新建一個數(shù)據(jù)庫連接conn
2、設(shè)置conn的autocommit為false
3、執(zhí)行test方法中的sql
4、又新建一個數(shù)據(jù)庫連接conn2
5、執(zhí)行a方法中的sql
6、拋出異常
7、執(zhí)行conn2的rollback()方法進行回滾
8、繼續(xù)拋異常,對于test()方法而言,它會接收到一個異常,然后拋出
9、執(zhí)行conn的rollback()方法進行回滾,最終還是兩個方法中的sql都回滾了

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

正常情況下,a()調(diào)用b()方法時,如果b()方法拋了異常,但是a()方法捕獲了,那么a()的事務(wù)還是會正常提交的,但是有的時候,我們捕獲異??赡苤皇遣话旬惓P畔⒎祷亟o客戶端,而是為了返回一些更優(yōu)良的錯誤信息,所以在這個時候,我們還是希望事務(wù)能回滾的,那就得告訴Spring把當(dāng)前事務(wù)回滾掉,做法就是:

@Transactional
public void test(){
 
    // 執(zhí)行sql
 	try {
  		b();
 	} catch (Exception e) {
  	// 構(gòu)造友好的錯誤信息返回
  	TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
 	}
    
}

public void b() throws Exception {
 	throw new Exception();
}

七、TransactionSynchronization

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

@Component
public class UserService {

 @Autowired
 private JdbcTemplate jdbcTemplate;

 @Autowired
 private UserService userService;

 @Transactional
 public void test(){
  TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {

   @Override
   public void suspend() {
    System.out.println("test被掛起");
   }

   @Override
   public void resume() {
    System.out.println("test被恢復(fù)");
   }

   @Override
   public void beforeCommit(boolean readOnly) {
    System.out.println("test準備要提交");
   }

   @Override
   public void beforeCompletion() {
    System.out.println("test準備要提交或回滾");
   }

   @Override
   public void afterCommit() {
    System.out.println("test提交成功");
   }

   @Override
   public void afterCompletion(int status) {
    System.out.println("test提交或回滾成功");
   }
  });

  jdbcTemplate.execute("insert into t1 values(1,1,1,1,'1')");
  System.out.println("test");
  userService.a();
 }

 @Transactional(propagation = Propagation.REQUIRES_NEW)
 public void a(){
  TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {

   @Override
   public void suspend() {
    System.out.println("a被掛起");
   }

   @Override
   public void resume() {
    System.out.println("a被恢復(fù)");
   }

   @Override
   public void beforeCommit(boolean readOnly) {
    System.out.println("a準備提交");
   }

   @Override
   public void beforeCompletion() {
    System.out.println("a準備提交或回滾");
   }

   @Override
   public void afterCommit() {
    System.out.println("a提交成功");
   }

   @Override
   public void afterCompletion(int status) {
    System.out.println("a提交或回滾成功");
   }
  });

  jdbcTemplate.execute("insert into t1 values(2,2,2,2,'2')");
  System.out.println("a");
 }

}

到此這篇關(guān)于Spring底層事務(wù)原理的文章就介紹到這了,更多相關(guān)Spring底層事務(wù)原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringMVC注解@CrossOrigin跨域問題詳解

    SpringMVC注解@CrossOrigin跨域問題詳解

    這篇文章主要介紹了SpringMVC注解@CrossOrigin跨域問題詳解,跨域是瀏覽同源策略的造成,是瀏覽器對JavaScript施加的安全限制CORS是一種可以解決跨域問題的技術(shù),需要的朋友可以參考下
    2023-11-11
  • Spring詳細講解循環(huán)依賴是什么

    Spring詳細講解循環(huán)依賴是什么

    這篇文章主要介紹了Java中的Spring循環(huán)依賴詳情,文章基于Java的相關(guān)資料展開詳細介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08
  • Java微服務(wù)分布式調(diào)度Elastic-job環(huán)境搭建及配置

    Java微服務(wù)分布式調(diào)度Elastic-job環(huán)境搭建及配置

    Elastic-Job在配置中提供了JobEventConfiguration,支持數(shù)據(jù)庫方式配置,會在數(shù)據(jù)庫中自動創(chuàng)建JOB_EXECUTION_LOG和JOB_STATUS_TRACE_LOG兩張表以及若干索引,來記錄作業(yè)的相關(guān)信息
    2023-02-02
  • Java單列集合Collection常用方法示例詳解

    Java單列集合Collection常用方法示例詳解

    這篇文章主要介紹了Java單列集合Collection常用方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11
  • Java非阻塞I/O模型之NIO相關(guān)知識總結(jié)

    Java非阻塞I/O模型之NIO相關(guān)知識總結(jié)

    在了解NIO (Non-Block I/O) 非阻塞I/O模型之前,我們可以先了解一下原始的BIO(Block I/O) 阻塞I/O模型,NIO模型能夠以非阻塞的方式更好的利用服務(wù)器資源,需要的朋友可以參考下
    2021-05-05
  • SpringBoot Aop 詳解和多種使用場景解析

    SpringBoot Aop 詳解和多種使用場景解析

    aop面向切面編程,是編程中一個很重要的思想本篇文章主要介紹的是SpringBoot切面Aop的使用和案例,對SpringBoot Aop相關(guān)知識感興趣的朋友跟隨小編一起看看吧
    2021-08-08
  • Mybatis實現(xiàn)一對一查詢映射處理

    Mybatis實現(xiàn)一對一查詢映射處理

    MyBatis是一種流行的Java持久化框架,它提供了靈活而強大的查詢映射功能,本文主要介紹了Mybatis實現(xiàn)一對一查詢映射處理,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08
  • Java transient關(guān)鍵字使用小記

    Java transient關(guān)鍵字使用小記

    這篇文章主要為大家詳細介紹了Java transient關(guān)鍵字的使用方法,感興趣的小伙伴們可以參考一下
    2016-06-06
  • 使用Java語言實現(xiàn)一個冒泡排序

    使用Java語言實現(xiàn)一個冒泡排序

    冒泡排序也是一種簡單直觀的排序算法,基本思想是多次遍歷要排序的數(shù)組,每次比較相鄰的元素,如果順序不對就交換它們的位置,本篇文章將通過IDE使用 Java 語言實現(xiàn)一個冒泡排序,需要的朋友可以參考下
    2024-03-03
  • logback?EvaluatorFilter日志過濾器源碼解讀

    logback?EvaluatorFilter日志過濾器源碼解讀

    這篇文章主要為大家介紹了logback?EvaluatorFilter日志過濾器源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11

最新評論