成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Spring @Transactional 注解是如何執行事務的?

開發 架構
相信小伙伴一定用過 @Transactional 注解,那 @Transactional 背后的秘密又知道多少呢?

 [[407478]]

前言

相信小伙伴一定用過 @Transactional 注解,那 @Transactional 背后的秘密又知道多少呢?

Spring 是如何開啟事務的?又是如何進行提交事務和關閉事務的呢?

1畫圖猜測

在開始 debug 閱讀源碼之前,小伙伴們應該已經知道 MySQL 是如何開啟事務的。

因此可以得出猜測:

那下面跟著源碼一起讀一讀,Spring 的 @Transactional 注解是如何執行事務邏輯的?

2Spring 事務執行流程

開啟事務

這里使用的是 Spring Boot + MySQL + Druid

  1. <dependency> 
  2.     <groupId>com.alibaba</groupId> 
  3.     <artifactId>druid-spring-boot-starter</artifactId> 
  4.     <version>1.2.6</version> 
  5. </dependency> 

在創建 Bean 的時候,會對 UserService 基于 AOP 生成代理對象;

AbstractAutowireCapableBeanFactory#initializeBean

...

wrapIfNecessary

AbstractAutoProxyCreator#createProxy CglibAopProxy#getProxy 生成代理對象

  • 開始執行 userService.updateUserInfo(); 這里的 userService 就是代理對象;會被 CglibAopProxy.DynamicAdvisedInterceptor#intercept 方法攔截;
  • TransactionInterceptor#invoke 被事務攔截器攔截
  • TransactionAspectSupport#invokeWithinTransaction 事務處理
  • AbstractPlatformTransactionManager#getTransaction 會在這里調用 AbstractPlatformTransactionManager#startTransaction 方法,來開啟事務。

是不是看到 doBegin 這個詞突然感覺很熟悉。

跟進 DataSourceTransactionManager#doBegin 方法,注意看,此時是在 spring-jdbc-5.3.8.jar 包下面的。

因為使用的 druid 連接池,所以這塊 Connection 是 durid 的連接池。

  • DruidPooledConnection#setAutoCommit(false) 關閉自動提交;

這里就是 druid 的邏輯,一頓執行然后到 com.alibaba.druid.filter.FilterChainImpl#connection_setAutoCommit。

  • ConnectionImpl#setAutoCommit,這個是在 mysql-connector-java-8.0.25.jar 包下的。

這一句才是重點 SET autocommit=0。

  1. SET autocommit=0 

開啟事務了!

總結一下流程:

執行 SQL

在開始事務之后,會通過回調執行方法的內部邏輯。

  • 因為這里使用的是 Mybatis,所以還是會被代理,MapperProxy#invoke;
  • DruidPooledPreparedStatement#execute;
  • ClientPreparedStatement#execute;

執行過程相對比較簡單:

提交事務

在 TransactionAspectSupport#invokeWithinTransaction 最后一行,commitTransactionAfterReturning(txInfo); 就是提交事務。

  • AbstractPlatformTransactionManager#commit 抽象事務管理器,進行提交事務
  • DataSourceTransactionManager#doCommit 數據源數據管理器,提交事務

這里肯定是調用連接池的方法,所以會執行到 DruidPooledConnection 中

  • DruidPooledConnection commit
  • 最終還是執行到 mysql-connector-java-8.0.25.jar 包下面的 ConnectionImpl#commit

調用 commit 提交事務。

  1. commit 

異常回滾

異常在這里 TransactionAspectSupport#invokeWithinTransaction 會被 catch。

AbstractPlatformTransactionManager#rollback 在這里進行 rollback

執行 DataSourceTransactionManager#doRollback

最終執行到 mysql-connector-java-8.0.25.jar 的 ConnectionImpl#rollback() 到 ConnectionImpl#rollbackNoChecks

從而執行 rollback 語句

  1. rollback 

恢復 autocommit

cleanupTransactionInfo(txInfo);

在 這個方法中會將之前設置的 autocommit 進行恢復。

3Java 原生開啟事務

如果覺得這樣有點繞,那咱們可以看簡單版本的,不帶 Spring。

  1. /** 
  2.  * @author liuzhihang 
  3.  * @date 2021/6/18 16:51 
  4.  */ 
  5. public class MainTest { 
  6.  
  7.  
  8.     public static void main(String[] args) throws Exception { 
  9.  
  10.         DruidDataSource dataSource = new DruidDataSource(); 
  11.         dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); 
  12.         dataSource.setUrl("jdbc:mysql://localhost:3306/demo"); 
  13.         dataSource.setUsername("root"); 
  14.         dataSource.setPassword("root"); 
  15.  
  16.         Connection connection = dataSource.getConnection(); 
  17.  
  18.         try { 
  19.             // 關閉自動提交 
  20.             connection.setAutoCommit(false); 
  21.  
  22.             connection.prepareStatement("update user_info set user_name = 'liuzhihang' where user_id = '1001';").executeUpdate(); 
  23.             connection.prepareStatement("update user_address set address = 'anhui' where user_id = '1001';").executeUpdate(); 
  24.             // 提交事務 
  25.             connection.commit(); 
  26.         } catch (Exception e) { 
  27.             // 回滾 
  28.             connection.rollback(); 
  29.         } finally { 
  30.             // 開啟自動提交 
  31.             connection.setAutoCommit(true); 
  32.         } 
  33.     } 

看完 Java 原生提交事務的方式,是不是感覺簡單明了。

Spring @Transactional 只是創建了 AOP 代理,通過代理調用原生的開啟關閉事務,同樣在執行 SQL 那一塊,也是 Mybatis 進行了代理,從而提交 SQL。

4總結

最后,將圖進行合并,總結流程。

至此,事務執行過程分析完畢。

不過還是有一個疑問?

為什么使用 set autocommit = 0 來開啟事務,而不是使用 begin 或者 start transaction 來開啟事務呢?

責任編輯:武曉燕 來源: 程序員小航
相關推薦

2023-05-05 07:39:04

Spring事務面試

2023-11-02 07:52:30

Java工具

2023-09-27 16:22:51

SpringMySQL原子性

2022-08-08 17:38:45

Spring策略事務

2023-09-28 09:07:54

注解失效場景

2009-11-12 14:26:34

ADO.NET執行事務

2025-01-06 09:26:49

2021-04-14 15:17:08

Transaction代碼語言

2025-01-16 08:45:48

2023-04-02 13:57:04

Java自定義事務管理器

2022-06-28 14:57:09

FormatterSpring

2025-05-07 00:20:00

@AsyncSpring事務

2024-04-07 00:00:05

事務Java開發

2024-12-17 16:26:31

2022-08-09 09:34:32

Spring開發

2020-10-19 11:05:17

SpringTransaction事務

2020-06-17 16:56:36

數據庫MySQL跨行事務

2017-08-22 17:10:45

數據庫MySQL事務模型

2020-11-17 08:28:55

數據庫

2024-01-08 08:45:07

Spring容器Bean
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日本精品久久久久久久 | 成人在线观看免费 | 美女福利视频网站 | 一区二区三区四区不卡 | 日本精品视频 | 日韩有码一区 | 日韩中文字幕网 | 亚洲www啪成人一区二区 | 国产精品亚洲一区二区三区在线 | 在线观看黄色 | 久久久久久久久国产 | 日本三级网址 | 日韩精品免费一区二区在线观看 | 婷婷久久五月 | 日韩欧美在线一区 | 国产成人精品区一区二区不卡 | 亚洲视频一区在线观看 | 国产精品区一区二区三 | 91亚洲国产亚洲国产 | 亚洲精品女优 | 亚洲国产欧美日韩 | 国产精品一区在线观看你懂的 | 2021天天干夜夜爽 | 国产精品一区二区三区四区 | av影音在线 | 精品国产乱码久久久久久丨区2区 | 日韩在线xx | 天天天堂 | 中文字幕国产在线 | 欧美日韩成人在线 | 亚洲精品美女 | 成人午夜激情 | 国产精品亚洲欧美日韩一区在线 | 久久精品网 | 国产免费一区二区 | 欧美一区二区免费 | 91麻豆产精品久久久久久夏晴子 | 99国产精品久久久 | 日本污视频 | 国产成人久久久 | 免费在线h视频 |