Mybatis事務源碼

使用

<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
</bean>

dataSource參數

事務自定義標籤
該命名空間肯定有對應的handler來進行調用相應的解析器來執行。
在這裏插入圖片描述
AnnotationDrivenBeanDefinitionParser類的parse方法
在這裏插入圖片描述

AopAutoProxyConfigurer.configureAutoProxyCreator這個默認方法
在這裏插入圖片描述

看到這裏,代碼就是爲TransactionAttributeSourceAdvisor這個bean中兩個屬性設置成TransactionAttributeSource和TransactionInterceptor。

第一行註冊了一個InfrastructureAdvisorAutoProxyCreator
在這裏插入圖片描述

再來看下InfrastructureAdvisorAutoProxyCreator這個類。
在這裏插入圖片描述
InfrastructureAdvisorAutoProxyCreator繼承了BPP接口,意味着是在初始化後對其需要的bean進行封裝成代理對象。
在這裏插入圖片描述
這裏的流程之前文章介紹了,我再來回顧一下吧。通過這個bean找出對應的增強方法,然後調用createProxy方法創建出來代理對象。

尋找所有的增強方法-BeanFactoryUtils.beanNamesForTypeIncludingAncestors
在這裏插入圖片描述
這裏的Advisor類,可以讓我們想到之前註冊的TransactionAttributeSourceAdvisor也是Advisor增強方法,自然獲取的時候會獲取到。
在這裏插入圖片描述
TransactionAttributeSourceAdvisor實現了PointcutAdvisor接口
在這裏插入圖片描述
第一個參數pointcut返回的TransactionAttributeSourcePoint類型的實例,該實例裏頭有getTransactionAttributeSource方法。
在這裏插入圖片描述
尋找該類時候的增強方法流程:先對所有增強方法進行循環,遍歷過程中對類的方法再次遍歷,查找匹配成功的增強方法。
在尋找相應增強方法流程中,需要提取事務標籤。

提取事務標籤computeTransactionAttribute
這裏method代表接口中的方法,specificMethods代表實現類中的方法。
在這裏插入圖片描述
先看方法上是否存在事務屬性,存在則使用方法上的屬性,否則使用方法所在類上的屬性,沒找到,則搜索接口方法中的屬性,再沒有搜索到,最後嘗試接口的類上面的聲明。
findTransactionAttribute方法就是用來解析我們聲明的屬性,propagation、isolation、readOnly等等。
在調用事務增強器增強的代理類時會首先執行TransactionInterceptor進行增強,同時調用invoke方法完成整個事務的邏輯

事務增強器TransactionInterceptor的invoke方法-在代理類執行相應方法時調用
在這裏插入圖片描述
invokeWithinTransaction方法
在這裏插入圖片描述
執行事務流程
1.獲取事務屬性(在將類轉爲代理類時,已經提取了事務屬性,上面描述了)
2.加載配置中的TransactionManager
3.不同的事務處理方式使用不同的邏輯。聲明式事務便於理解。
4.在目標方法執行前獲取事務並收集事務信息。TransactionInfo中包含TransactionAttribute,所以事務信息和事務屬性並不相同。TransactionInfo還包括PlatformTransactionManager以及TransactionStatus相關信息。
5.執行目標方法
6.一旦出現異常,嘗試異常處理。
7.提交事務前的事務信息清除。
8.提交事務。

接下來看一下事務創建的過程-創建事務信息
在這裏插入圖片描述
getTransaction方法用於獲取事務

看下doGetTransaction方法
在這裏插入圖片描述
看一下事務傳播行爲,可以看到MANDATORY在沒有事務時會拋出異常。
在這裏插入圖片描述
緊接着doBegin方法處理數據庫連接設置-個人認爲是獲取新事務
在這裏插入圖片描述

事務準備工作流程getTransaction方法
1.獲取事務 doGetTransaction方法。
2.如果當前線程存在事務,則轉向嵌套事務的處理handleExistingTransaction。
3.事務超時設置驗證
4.事務getPropagationBehavior傳播行爲的一些驗證
5.構建DefaultTransactionStatus
6.完善transaction,包括設置ConnectionHolder、隔離級別、timeout。如果是新連接,綁定到當前線程。
在這裏插入圖片描述
doBegin方法流程
1.如果不存在connectionHolder則嘗試獲取新連接,如果當前線程已經存在connectionHolder,則沒必要再次獲取(之前判斷過線程是否有連接並且是否存在事務。如果沒有事務的話,可能會進來,直接用原來的連接)。對於事務同步表示設置爲true的需要重新獲取連接。
2.DataSourceUtils.prepareConnectionForTransaction中設置了隔離級別並給connection設置只讀標識。
3.更改默認的提交設置
4.設置標誌位,標識當前連接已被事務激活。
5.設置過期時間。
6.將connectionHolder綁定到當前線程。

當存在事務情況下會執行handleExistingTransaction方法,掛起使用suspend方法
在這裏插入圖片描述
當建立事務連接並完成事務信息的提取後,將事務信息統一記錄在TransactionInfo實例中。包含了目標方法一開始的所有狀態信息。

回滾處理completeTransactionAfterThrowing
拋出異常時會先判斷是否存在事務,如果存在事務調用rollbackOn方法判斷是否是RuntimeException或者Error類型,如果是這些類型,那麼可以進行回滾,如果不是那麼進行提交併拋出異常。如果不存在事務,什麼都不用管。
在這裏插入圖片描述
回滾處理的大致實現
在這裏插入圖片描述
1.首先是自定義觸發器的調用,包括在回滾前、完成回滾後的調用。
2.當之前已經保存的事務信息中有保存點信息,使用保存點信息進行回滾。常用於嵌套式事務。 內嵌的事務不會引起外嵌的回滾。
當之前已經保存的事務信息中事務爲新事務,那麼直接回滾。在裏頭會調用connection的rollback方法。
在這裏插入圖片描述
3.回滾後的信息清除。設置完成表示避免重複調用
4.如果事務執行前有事務掛起,那麼當事務執行結束需要將掛起的事務恢復。
在這裏插入圖片描述
最後是事務提交commitTransactionAfterReturning方法
在這裏插入圖片描述
在提交的過程並不是直接提交的,而是考慮很多種情況。主要是因爲嵌套事務情況。Spring將嵌套事務開始之前設置保存點,一旦嵌套事務出現異常便會回滾。但如果沒有出現異常,內嵌事務也不會提交,而是由外層事務負責提交。
1.當事務狀態中有保存點信息的話,不去提交。
2.如果非新事務,也不會執行提交。(如果有事務,在該事務中允許,就是非新事務吧)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章