Spring AOP原理分析介紹了AOP的一些細節,有了這篇文章的基礎,我們再來分析Spring中聲明式事務的實現就能夠輕車熟路一些。
一些概念
事務可以分爲2種,全局事務與本地事務。
全局事務可以保證多數據源下的事務特性(關於事務的ACID特性這裏不詳說),本地事務則可以保證單個數據源下的事務特性。全局事務使用JTA,支持多事務源事務(通過XA協議來支持,然而XA性能較低,一般都會採取別的分佈式事務方案,比如事務消息,補償方案等);本地事務則基於JDBC連接,不支持分佈式事務。
事務管理器
Spring使用事務管理器來管理事務,下面的接口是Spring事務管理器的統一抽象接口,我們可以根據需要實現自己的事務管理器。Spring提供了許多事務平臺默認的實現,比如基於JDBC的DataSourceTransactionManager,基於JTA的JtaTransactionManager,基於Hibernate的HibernateTransactionManager等。
其中getTransaction(..)方法根據TransactionDefinition參數返回一個TransactionStatus對象。如果當前調用堆棧中存在匹配的事務,則返回的TransactionStatus可能表示一個新事務,也可能表示一個現有事務,由TransactionDefinition來決定。
TransactionDefinition定義了很多常量,代表着不同的含義
以Propagation開頭的代表傳播行爲:在事務範圍內執行的所有代碼都在該事務中運行,但是,如果事務方法在事務上下文已經存在時執行,則可以指定行爲。例如,代碼可以在現有事務中繼續運行(通常情況下),或者可以掛起現有事務並創建一個新事務
以Isolation開頭的代表隔離程度:即事務的隔離級別
getTimeout方法:獲取事務的超時時間
isReadOnly方法(只讀狀態):是否爲只讀狀態
getPropagationBehavior方法:獲取傳播行爲
getIsolationLevel:獲取隔離程度
傳播行爲與隔離級別
由接口中的常量可知,共有7種傳播行爲,分別爲:
REQUIRED:如果當前範圍不存在事務,則新建一個事務(默認)
REQUIRES_NEW:總是新建一個事務。
NESTED:如果當前有事務,則在嵌套事務內執行,如果當前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。僅適用於JDBC事務,本質上是根據JDBC回滾點回滾指定範圍內的操作,NESTED和REQUIRES_NEW都可以做到內部方法事務回滾而不影響外圍方法事務。但是因爲NESTED是嵌套事務,所以外圍方法回滾之後,作爲外圍方法事務的子事務也會被回滾。而REQUIRES_NEW是通過開啓新的事務實現的,內部事務和外圍事務是兩個事務,外圍事務回滾不會影響內部事務。
SUPPORTS:支持當前事務,如果當前沒有事務,就以非事務方式執行。
MANDATORY:使用當前的事務,如果當前沒有事務,就拋出異常。
NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
NEVER:以非事務方式執行,如果當前存在事務,則拋出異常。
一般情況下我們使用默認的傳播行爲即可。
隔離級別對應的就是數據庫的隔離級別,其中有個DEFAULT,代表着默認的隔離級別,他是跟着底層數據庫變化的,例如如果是MySQL的話,那麼默認的隔離級別就是可重複讀。
聲明式事務
Spring中事務管理分爲編程式事務與聲明式事務,Spring官方建議使用聲明式事務進行事務管理,對代碼侵入性較小。
回滾:默認情況下,Spring只對RunTimeException與Error類型的異常進行回滾,我們也可以指定發生某些異常不會滾或者發生某些異常回滾
聲明式事務使用@Transactional來實現,由於Spring中事務由代理實現,所以AOP的問題事務管理同樣會有:應該只將@Transactional應用於public方法。如果使用@Transactional註釋private,事務並不會生效。在代理模式(這是缺省模式)中,只攔截通過代理傳入的外部方法調用。這意味着自調用(實際上,目標對象中的一個方法調用目標對象的另一個方法)不會在運行時執行事務,即使被調用的方法被標記爲@Transactional。
源碼分析
同Spring AOP一文的分析類似,開啓事務的註解爲@EnableTransactionManagement,從該註解開始分析。
如果是代理模式(默認)則導入AutoProxyRegistrar與ProxyTransactionManagementConfiguration倆個組件。
AutoProxyRegistrar類中最終註冊了InfrastructureAdvisorAutoProxyCreator。
InfrastructureAdvisorAutoProxyCreator是一個後置處理器,我們找到後置處理器相關的接口,在對象創建以後,將對象包裝成代理對象返回
ProxyTransactionManagementConfiguration類註冊了BeanFactoryTransactionAttributeSourceAdvisor與AnnotationTransactionAttributeSource
AnnotationTransactionAttributeSource中的各種TransactionAnnotationParser負責解析事務相應的註解。
另一個bean爲TransactionInterceptor事務攔截器,其中保存了事務的屬性與事務管理器
找到動態代理相關的實現類,查看invoke方法
如果是事務方法則會進入到createTransactionIfNecessary方法開始一個事務,invocation.proceedWithInvocation();執行方法中操作。
如果發生異常則調用completeTransactionAfterThrowing(txInfo, ex);
判斷註解中是否指定了回滾的異常,根據異常做相應的回滾操作
最後調用commitTransactionAfterReturning(txInfo);進行事務的提交。
總結:找到被事務註解註釋的相關bean,爲bean生成代理對象,在對象方法執行時執行代理對象的invoke方法,做相應的事務操作。總體流程和AOP是一樣的。