深入理解spring事務原理,手動實現事務提交和回滾

1.其實最開始不知道怎麼寫,後來想想,想要把一件事情,用“人話”講明白,就需要從最簡單的開始,再逐步加入難度。
2.爲什麼,非要寫代碼呢?有兩點:第一:驗證自己的思想和邏輯,第二:鍛鍊自己的編碼能力。
3.搭建項目的時候,遇到來AOP失效的問題。解決方法在:springboot中aop切面失效,導致註解不起作用
4.爲什麼要自己實現,而不用框架呢?只有這樣,才能真正領悟框架的底層和精髓。

NO1.框架自動提交事務與異常回滾

先講一下場景吧,我要刪除數據庫中的一條記錄,那麼刪除的結果有兩種,一種是刪除成功,提交事務,另外一種是執行刪除的過程中發生異常,回滾事務。
但是,在實際開發過程中,我們從來不直接操作數據庫,而是通過ORM框架來操作或者Java相關框架來幹這個活!
今天也不例外,我們用springboot + jdbcTemplate來實現這個操作的過程。

在這裏插入圖片描述
這段代碼,我想大家都認識,並且也經常寫,但是,用的不是jdbcTemplate,而是調用mybatis。效果一樣,爲來快速實現,我們用jdbcTemplate實現。

需要注意的地方

@Transactional中的rollbackFor必須加上,否則回滾不生效。
如果,你不信,你可以自己寫代碼試試

NO2.控制框架的提交和事務回滾

第一個問題:我們用來jdbcTemplate,我們是否可以控制事務的提交和回滾嗎?

答案是肯定的,那需要怎麼做呢?

在這裏插入圖片描述
既然,我們要控制事務的提交,那麼我們就需要拿到sql鏈接,也就是connection.
那麼,connection從哪裏獲取呢?當然,是從DataSource中獲取了。

第二個問題:如果,不用DataSource,怎麼獲取鏈接呢?

在Springboot中,因爲配置了DataSource,所以,DataSource替我們去獲取了數據庫的connection。如果,沒有DataSource,我們怎麼獲取connection呢?這個應該是一個最基礎的了,就是通過JDBC去獲取connection。在最初學習Java的時候,我們不用任何ORM框架操作數據庫,就是用JDBC實現的。
其實,市面上的ORM框架也都是封裝了JDBC的功能,並實現了sql解析、參數映射、結果映射等功能,爲了就是簡化開發人員的工作量,提高開發人員的工作效率。
但是,這也導致越來越多的開發人員,根本不知道JDBC的存在了。
只是會用了工具,不知道工具是怎麼做的。一旦,工具出了問題,根本不知道怎麼修理。

NO3.AOP+註解實現事務的提交和回滾

第三個問題:從上面的兩段代碼,你能總結出上面規律?

第一個,是通過Springboot的jdbcTemplate來實現事務的操作,我只要懂得API就可以了。
第二個,想看看框架的執行流程是怎麼樣子的,所以,我來手動控制了事務的提交和回滾。
第三個,分析第二段代碼,我發現幾個我一直很疑惑的問題:

  • 事務提交,是怎麼由框架來提交的,原來就是框架替我們做來獲取鏈接,並且設置不自動提交,在我們的業務代碼執行完成以後,再提交的。
  • 事務回滾,就是在我們業務代碼執行出現異常的時候,進行事務回滾的。
  • 是不是,突然間豁然開朗,就是這麼一個思想,我們只需要關心業務代碼,系統或者框架來幫你操作事務。

第四個問題:既然,知道了思想,那麼讓我們自己來實現,你會怎麼樣實現呢?

這種思想和動態代理是不是很像,我們要做的就是給業務類的方法增強。增強的部分就是獲取數據庫鏈接,實現事務的提交和回滾。
在使用Spring開發的過程中,我們可以用Spring的aop來實現這個功能。

在這裏插入圖片描述

代碼並不多,我講一下我的整個思路和關鍵類

  • 我封裝了一個MyTemplate,主要用於獲取connection和執行sql語句
    在這裏插入圖片描述
  • 我定義了一個註解@MyTransactional,用於切面類MyTransactionalAop使用
    在這裏插入圖片描述

第五個問題:兩條sql語句或者多條sql語句,如何實現事務的提交和回滾呢?

答案是,必須在一個connection中執行,才能進行事務的操作。

第六個問題:如何才能保證執sql語句的connection是同一個呢?

這個就用到了ThreadLocal,其中的知識點是線程封閉,這裏就不展開說了,大家自己去了解一下吧!

第七個問題:spring中@Transactional的原理,能不能講一下?

你們覺得,註解的原理是什麼?我覺得,@Transactional只是註解,真正調用的地方是獲取註解中的相關配置屬性,然後在Connection提交事務的時候來做業務判斷而已。如何獲取,在Spring中最經典的就是通過AOP+反射。

NO4.spring事務源碼解讀

TransactionSynchronizationManager(事務管理器 )

看源碼速記方法,類名#方法名–操作
一般看源碼的時候,真正操作的地方,都是以doxxxx開頭的。

DataSourceUtils#getConnection–獲取鏈接
DataSourceUtils#doGetConnection–獲取鏈接操作,從TransactionSynchronizationManager中獲取
TransactionSynchronizationManager#getResource–獲取資源
TransactionSynchronizationManager#doGetResource–從resources獲取資源值,resources是一個ThreadLocal

TransactionAttributeSource(事務註解屬性資源)

TransactionAttributeSourceAdvisor#transactionInterceptor
TransactionAttributeSourcePointcut#TransactionAttributeSourceClassFilter#matches
AnnotationTransactionAttributeSource#isCandidateClass–解析並設置屬性
SpringTransactionAnnotationParser#isCandidateClass–解析註解策略

總結:

通過上面幾個簡單的類,我們就實現了事務的控制。其實,實現沒那麼複雜,重要的思想。通過閱讀源碼,我們知道了事務註解,是通過AOP來完成的。是不是和我實現的思想是一樣的?

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