Spring中的編程式事務和聲明式事務
spring中控制事務的方式有兩種:編程式事務和聲明式事務,今天我以兩種事務出發(fā),對spring中實現事務的@EnableTransactionManagement和@Transaction兩個注解的底層原理進行討論。
一、編程式事務
什么是編程式事務?
硬編碼的方式實現事務,在代碼中手動開始、提交和回滾事務
編程式事務實現思想是什么?
- 配置PlatformTransactionManager事務管理器去控制事務
- 配置TransactionDefinition設置事務屬性
- 配置TransactionTemplate控制事務
步驟和原理
1、定義數據源

2、定義一個PlatformTransactionManager 事務管理器,指定數據源。控制事務的操作(開始、提交、回滾)


3、定義TransactionDefinition 事務屬性,可以配置事務屬性信息

4、開啟事務操作。通過調用getTransaction方法



補充:ThreadLocal中存儲了datasource和connection的映射
這樣當我們開啟事務的時候會創(chuàng)建一個數據庫連接,通過ThreadLocal保證線程的同步

5、執(zhí)行業(yè)務操作

6、commit提交/rollback回滾事務

優(yōu)缺點
優(yōu)點:
- 以在代碼中精確地控制事務的起始點、提交點和回滾點
- 實現更細粒度的事務管理
缺點:
- 代碼侵入性:編程式事務管理會將事務管理邏輯直接嵌入到業(yè)務代碼中,增加了代碼的復雜度和維護成本,使得業(yè)務邏輯與事務管理耦合在一起。
- 重復性工作:在多個業(yè)務方法中可能需要重復編寫事務管理邏輯,增加了代碼冗余和維護工作量。
二、聲明式事務
什么是聲明式事務?
通過配置的方式去管理事務,可以是xml配置文件,也可以使用spring提供的@Transactional注解
聲明式事務實現思想是什么?
- 添加@EnableTransactionManagement注解
- 添加@Transactional注解
步驟和原理
1、啟用事務管理功能-配置類上加上@EnableTransactionManagement注解

2、定義事務管理器


3、需要開啟事務的目標接口/類/方法上添加@Transaction注解


4、執(zhí)行業(yè)務邏輯

5、啟動spring容器,獲取bean執(zhí)行業(yè)務邏輯

優(yōu)缺點
優(yōu)點:
- 與業(yè)務邏輯分離:聲明式事務管理將事務管理邏輯從業(yè)務代碼中分離出來,使得業(yè)務邏輯更清晰,降低了代碼的耦合性。
- 配置簡單:通過注解或XML配置,可以簡單地定義事務的傳播行為、隔離級別等屬性,而無需在每個業(yè)務方法中編寫重復的事務管理代碼。
- 易于維護:由于事務管理邏輯集中在配置中,易于維護和修改,提高了代碼的可讀性和可維護性。
- 提高一致性:聲明式事務管理可以確保在所有業(yè)務方法中都應用相同的事務管理策略,提高了事務管理的一致性。
缺點:
- 靈活性有限:聲明式事務管理的靈活性相對較低,無法在運行時動態(tài)地改變事務管理策略,有一定的局限性。
- RPC遠程調用成功,但是本地事務回滾了,RPC調用無法回滾。并且事務中有遠程調用,會拉長整個事務,導致本地事務的數據庫連接一致被占用,最后可能會導致數據庫連接池耗盡

在阿里巴巴的開發(fā)手冊中也明確標出,我們用@Transactional注解的時候要謹慎,大家在業(yè)務場景中要謹慎使用哦!

上面我已經對spring實現事務的兩種方式分別進行了說明,下面我們看看它的源碼,解開事務這個神秘面紗!
三、源碼分析
@EnableTransactionManagement

作用是什么?
開啟spring自動管理事務。在spring容器啟動的時候,會攔截所有bean的創(chuàng)建,判斷當前bean中有沒有用@Transaction注解,是不是需要讓spring管理事務
判斷規(guī)則:
- public方法上有沒有用@Transaction注解和bean的類相關的類/接口上有沒有用@Transaction注解
- 當滿足規(guī)則之后會通過aop的方式創(chuàng)建代理,并且在代理中添加一個TransactionInterceptor攔截器
注意:@Transaction注解在代理對象被創(chuàng)建并且方法被調用時生效
@Transactional注解生效,必須確保Spring能夠為目標類創(chuàng)建代理對象,并且方法通過代理對象調用
TransactionInterceptor攔截器的作用是什么?
攔截@Transaction方法,在方法前后添加事務額外邏輯
如果代理中還有其他攔截器,攔截器的順序如何指定呢?
通過order()方法修改事務攔截器的執(zhí)行順序
注意:默認值是 LOWEST_PRECEDENCE = Integer.MAX_VALUE,攔截器的執(zhí)行順序是order升序
int order() default Ordered.LOWEST_PRECEDENCE;
@Import(TransactionManagementConfigurationSelector.class)在這里的作用是什么?
@Import的作用是批量導入需要注冊的類,完成bean的注冊
那@Import導入了哪些類?
通過點進去TransactionManagementConfigurationSelector我們發(fā)現,里面有一個selectImports方法,這個方法的返回值是一個字符串數組,返回的字符串數組如果是正常的全限定類名才會被容器識別
通過查看selectImports方法源碼,我們發(fā)現return了兩個類-AutoProxyRegistrar、ProxyTransactionManageMentConfiguration,也就是說Import導入了這兩個類
- AutoProxyRegistrar:啟用spring aop功能,創(chuàng)建代理
- ProxyTransactionManageMentConfiguration:在aop中添加事務攔截器

①、AutoProxyRegistrar
點進源碼,我們看registerBeanDefinitions這個方法,看過spring容器啟動流程的小伙伴會發(fā)現,其中流程就會調用這個方法,AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)作用是向spring容器注冊一個自動代理創(chuàng)建器,從而啟用AOP代理的功能

在方法內部會導入InfrastructureAdvisorAutoProxyCreator類,給spring 容器中注冊了一個后置處理器-BeanPostProcessor,攔截所有bean的創(chuàng)建并將符合規(guī)則的bean創(chuàng)建代理,對類進行增強

在生命周期階段,創(chuàng)建bean的時候只有需要增強,就會調用BeanPostProcessor的after進行增強
②、ProxyTransactionManageMentConfiguration
配置類,一般是提供加了@Bean的一些方法。注冊了一個事務攔截器TransactionInterceptor

總結
通過對上面兩個導入的類的源碼分析我們明確了他們的作用,我們使用@Transaction標注的bean會通過AutoProxyRegistrar去啟用aop功能,通過ProxyTransactionManagementConfiguration在aop中添加事務攔截器從而實現事務管理
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
關于pom.xml中maven無法下載springcloud包問題
小編遇到這樣一個問題spring-cloud-starter-feign,spring-cloud-starter-eureka 一直無法下載,maven倉庫中包路徑顯示為unknown,怎么解決呢?下面小編給大家?guī)砹藀om.xml中maven無法下載springcloud包問題,需要的朋友可以參考下2022-08-08
關于@GetMapping和@GetMapping(value=““)的區(qū)別
這篇文章主要介紹了關于@GetMapping和@GetMapping(value=““)的區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-05-05

