Java?Spring?AOP源碼解析之事務(wù)實現(xiàn)原理
不用Spring管理事務(wù)?
讓我們先來看一下不用spring管理事務(wù)時,各種框架是如何管理事務(wù)的
使用JDBC來管理事務(wù)
使用Hibernate來管理事務(wù)
業(yè)務(wù)邏輯和事務(wù)代碼是耦合到一塊的,并且和框架的具體api綁定了。當我們換一種框架來實現(xiàn)時,里面對事務(wù)控制的代碼就要推倒重寫,并不一定能保證替換后的api和之前的api有相同的行為。
基于這些問題,Spring抽象了一些事務(wù)相關(guān)的頂層接口,我們面向接口編程,換框架時只要換具體的實現(xiàn)即可。有點像JDBC API的味道了
常用api | 接口 |
---|---|
PlatformTransactionManager | 對事務(wù)進行管理 |
TransactionDefinition | 定義事務(wù)的相關(guān)屬性,例如隔離級別,傳播行為 |
TransactionStatus | 保存事務(wù)狀態(tài) |
針對不同的數(shù)據(jù)訪問技術(shù),使用不用的PlatformTransactionManager類即可
數(shù)據(jù)訪問技術(shù) | PlatformTransactionManager實現(xiàn)類 |
---|---|
JDBC/Mybatis | DataSourceTransactionManager |
Hibernate | HibernateTransactionManager |
Jpa | JpaTransactionManager |
Jms | JmsTransactionManager |
編程式事務(wù)管理
使用PlatformTransactionManager
使用TransactionTemplate
當我們直接使用PlatformTransactionManager來管理事務(wù)時,有很多模版代碼。例如業(yè)務(wù)代碼正常執(zhí)行,提交事務(wù),否則回滾事務(wù)。我們可以把這部分模版代碼封裝成一個模版類,這樣使用起來就很方便了,如下所示
如下圖所示,TransactionTemplate#execute方法就是一個典型的模版方法
我們可以傳入如下2個接口的實現(xiàn)類來執(zhí)行業(yè)務(wù)邏輯,TransactionCallback(需要返回執(zhí)行結(jié)果)或TransactionCallbackWithoutResult(不需要返回結(jié)果)
聲明式事務(wù)管理
為了讓使用更加簡潔,Spring直接把事務(wù)代碼的執(zhí)行放到切面中了,我們只需要在業(yè)務(wù)代碼方法上加上一個@Transactional注解即可,這種方式我們最常用哈
使用@Transactional注解
此時事務(wù)相關(guān)的定義我們就可以通過@Transactional注解來設(shè)置了
屬性名 | 類型 | 描述 | 默認值 |
---|---|---|---|
value(和transactionManager互為別名) | String | 當在配置文件中有多個PlatformTransactionManager ,用該屬性指定選擇哪個事務(wù)管理器 | 空字符串"" |
propagation | 枚舉:Propagation | 事務(wù)的傳播行為 | REQUIRED |
isolation | 枚舉:Isolation | 事務(wù)的隔離度 | DEFAULT |
timeout | int | 事務(wù)的超時時間。如果超過該時間限制但事務(wù)還沒有完成,則自動回滾事務(wù) | -1 |
readOnly | boolean | 指定事務(wù)是否為只讀事務(wù) | false |
rollbackFor | Class[] | 需要回滾的異常 | 空數(shù)組{} |
rollbackForClassName | String[] | 需要回滾的異常類名 | 空數(shù)組{} |
noRollbackFor | Class[] | 不需要回滾的異常 | 空數(shù)組{} |
noRollbackForClassName | String[] | 不需要回滾的異常類名 | 空數(shù)組{} |
源碼解析
我們需要在配置類上加上@EnableTransactionManagement注解,來開啟spring事務(wù)管理功能,@EnableTransactionManagement最主要的功能就是注入一個TransactionInterceptor攔截器,來控制事務(wù)開啟,提交或者回滾
ProxyTransactionManagementConfiguration
TransactionInterceptor#invoke
TransactionAspectSupport#invokeWithinTransaction
TransactionAspectSupport#createTransactionIfNecessary
當開啟事務(wù)的時候,可以看到各種傳播屬性的行為
AbstractPlatformTransactionManager#getTransaction
Spring事務(wù)的傳播行為在Propagation枚舉類中定義了如下幾種選擇
支持當前事務(wù)
REQUIRED
:如果當前存在事務(wù),則加入該事務(wù)。如果當前沒有事務(wù),則創(chuàng)建一個新的事務(wù)SUPPORTS
:如果當前存在事務(wù),則加入該事務(wù) 。如果當前沒有事務(wù), 則以非事務(wù)的方式繼續(xù)運行MANDATORY
:如果當前存在事務(wù),則加入該事務(wù) 。如果當前沒有事務(wù),則拋出異常
不支持當前事務(wù)
REQUIRES_NEW
:創(chuàng)建一個新事務(wù),如果當前存在事務(wù),則把當前事務(wù)掛起NOT_SUPPORTED
: 以非事務(wù)方式運行,如果當前存在事務(wù),則把當前事務(wù)掛起NEVER
: 以非事務(wù)方式運行,如果當前存在事務(wù),則拋出異常
其他情況
NESTED
:如果當前存在事務(wù),則創(chuàng)建一個事務(wù)作為當前事務(wù)的嵌套事務(wù)來執(zhí)行 。如果當前沒有事務(wù),則該取值等價于REQUIRED
以NESTED啟動的事務(wù)內(nèi)嵌于外部事務(wù)中 (如果存在外部事務(wù)的話),此時內(nèi)嵌事務(wù)并不是一個獨立的事務(wù),它依賴于外部事務(wù)。只有通過外部事務(wù)的提交,才能引起內(nèi)部事務(wù)的提交,嵌套的子事務(wù)不能單獨提交
參考博客
http://www.dbjr.com.cn/article/229456.htm
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Mybatis-Plus3.x的創(chuàng)建步驟及使用教程
MyBatis-Plus是一個?MyBatis?的增強工具,在?MyBatis?的基礎(chǔ)上只做增強不做改變,為?簡化開發(fā)、提高效率而生,這篇文章主要介紹了Mybatis-Plus3.x的使用,需要的朋友可以參考下2023-10-10SpringMVC空指針異常NullPointerException解決及原理解析
這篇文章主要介紹了SpringMVC空指針異常NullPointerException解決及原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-08-08JVM實戰(zhàn)系列之CPU100%和內(nèi)存100%排查
本文主要介紹了JVM實戰(zhàn)系列之CPU100%和內(nèi)存100%排查,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-06-06CompletableFuture并行處理List分批數(shù)據(jù)demo
這篇文章主要介紹了CompletableFuture并行處理List分批數(shù)據(jù)實現(xiàn)實例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-11-11Spring Boot 中常用的注解@RequestParam及基本用法
@RequestParam 是 Spring Framework 和 Spring Boot 中常用的注解之一,用于從請求中獲取參數(shù)值,本文給大家介紹Spring Boot 中常用的注解@RequestParam,感興趣的朋友一起看看吧2023-10-10