Spring事務(wù)架構(gòu)詳解一:PlatformTransactionManager

?一、PlatformTransactionManager

? ? ? ?1、架構(gòu)設(shè)計理念讓事務(wù)的關(guān)注點與數(shù)據(jù)訪問關(guān)注點分離

? ? ? ?2、PlatformTransactionManager是該架構(gòu)的核心接口,為應(yīng)用程序提供事務(wù)界定的統(tǒng)一方式

? ? ? ? 3、PlatformTransactionManager負責界定事務(wù)邊界,TransactionDefinition負責定義事務(wù)屬性(隔離級別、傳播行為),PlatformTransactionManager將參照TransactionDefinition的屬性定義來開啟相關(guān)事務(wù)。事務(wù)開啟之后到事務(wù)結(jié)束期間的事務(wù)狀態(tài)由TransactionStatus負責,我們也可以通過TransactionStatus對事務(wù)進行有限的控制?!?/p>

類圖

1、Spring的事務(wù)抽象框架以PlatformTransactionManager作為頂層抽象接口,具體的實現(xiàn)交給不同的實現(xiàn)類,使用對象可以根據(jù)當前場景,選擇使用或者替換哪一個具體的實現(xiàn)類。從這個層次看,整個框架的設(shè)計是以Strategy模式為基礎(chǔ)的。不過,從各個實現(xiàn)類的繼承層次上來看,Spring 事務(wù)框架的實現(xiàn)則更多地依賴于模板方法模式。

2、org.springframework.transaction.support.AbstractPlatformTransactionManager作為DataSourceTransactionManager的父類,以模板方法的形式封裝了固定的事務(wù)處理邏輯,而只將與事務(wù)資源相關(guān)的操作以protected或者abstract方法的形式留給DataSourceTransactionManager 來實現(xiàn)。作為模板方法父類,AbstractPlatformTransactionManager替各子類實現(xiàn)了以下固定的?N 務(wù)內(nèi)部處理邏輯:

□判定是否存在當前事務(wù),然后根據(jù)判斷結(jié)果執(zhí)行不同的處理邏輯;

□結(jié)合是否存在當前事務(wù)的情況,根據(jù)TransactionDefinition中指定的傳播行為的不同語義執(zhí)行后繼邏輯;

□根據(jù)情況掛起或者恢復事務(wù);

□提交事務(wù)之前檢查readonly字段是否被設(shè)置,如果是的話,以事務(wù)的回滾代替事務(wù)的提交;

□在事務(wù)回滾的情況下,清理并恢復事務(wù)狀態(tài):

□如果事務(wù)的Synchonization處于active狀態(tài),在事務(wù)處理的規(guī)定時點觸發(fā)注冊的Synchonization 回調(diào)接口。

這些固定的事務(wù)內(nèi)部處理邏輯大都體現(xiàn)在以下幾個主要的模板方法中:

□ public final Transactionstatus getTrcinsaction(TransactionDefinitiondefinition) throws TransactionException

□ public final void rollback(Transactionstatus status) throws TransactionException

□ public final void commit(Transactionstatus status) throws TransactionException

□?protected final SuspendedResourcesHolder suspend(0bject transaction) throws TransactionException

□?protected final void resume(Object transaction, SuspendedResourcesHolder resourcesHolder) throws TransactionException

下面詳細介紹幾個模板方法:

2.1、getTransaction(TransactionDefinition)開始。getTransaction (TransactionDefinition)的主要目的是開啟一個事務(wù),但需要在此之前判斷一下之前是否存在一個事務(wù)。如果存在,則根據(jù)TransactionDefinition中的傳播行為決定是掛起當前事務(wù)還是拋出異常。同樣的,不存在事務(wù)的情況下,也需要根據(jù)傳播行為的具體語義來決定如何處理。

1)獲取transaction object,以判斷是否存在當前事務(wù)。

以上這行代碼有如下兩點需要申明。

□ 獲取的transaction object類型會因具體實現(xiàn)類的不同而各異,DataSourceTransactionManager 會返回DataSourceTransactionManager. DataSourceTransacCionObject 類型實例,HibernateTransactionManager會返回HibernateTransactionManager.HibernateTransactionObject類型的實例,等等。AbstractPlatformTransactionManager不需要知道具體實現(xiàn)類返回的transaction object具體類型是什么,因為最終對transaction object的依賴都將通過方法參數(shù)進行傳遞,只要具體的實現(xiàn)類在取得transaction object參數(shù)后知道如何轉(zhuǎn)型就行,所以,這一步返回的transact ion為Object類型。

□ doGetTransaction()是getTransaction(TransactionDefinition)模板方法公開給子類來實現(xiàn)的abstract 類型方法。DataSourceTransactionManager 在實現(xiàn)doGetTransaction ()方法邏輯的時候,會從TransactionSynchronizationManager獲取綁定的資源,然后添加到DataSourceTransactionObject之后返回。

2)檢驗TransactionDefinition參數(shù)合法性。如以下代碼所示:

if (definition == null)(

? ??????definition = new DefaultTransactionDefinition;

)

如果definition參數(shù)為空,則創(chuàng)建一個DefaultTransactionDefinition實例以提供默認的事務(wù)定義數(shù)據(jù)。

3)根據(jù)先前獲得的transaction object判斷是否存在當前事務(wù),根據(jù)判定結(jié)果采取不同的處理方式。

默認情況下,isExistingTransaction(transaction)返回false,該方法需要具體子類根據(jù)情況進行覆寫。對于DataSourceTransactionManager來說,它會根據(jù)傳入的transaction所記載的信息進行判斷,如下所示:

(a)如果isExistingTransaction(transaction)方法返回true,即存在當前事務(wù)的情況下,由handleExistingTransaction ()方法統(tǒng)處理存在當前事務(wù),應(yīng)該如何創(chuàng)建事務(wù)對應(yīng)的Transactionstatus 實例并返回。

如果definition定義的傳播行為是PROPAGATI0N_NEVER,拋出異常并退出.如下:

如果definition定義的傳播行為是PROPAGATION_NOT_SUPPORTED,則掛起當前事務(wù),然后返回. 如下:

newTransactionStatus()方法返回一個DefaultTransactionStatus實例,因為我們掛起了當前事務(wù)。而PROPAGATION_NOT_SUPPORTED不需要事務(wù),所以,返回的DefaultTransactionStatus 不包含transaction object的信息(構(gòu)造方法第二個參數(shù))。

如果definition定義的傳播行為是PROPAGATION-REQUIRES_NEW,則同樣掛起當前事務(wù),并開始—個新的事務(wù)并返回.如下:

AbstractPlatformTransactionManager首先將當前事務(wù)掛起,然后調(diào)用doBegin()方法開始新的事務(wù)。如果開始事務(wù)過程中出現(xiàn)異常,那么恢復之前掛起的事務(wù)。doBegin(transaction, definition)方法為abstract方法,需要具體子類來實現(xiàn)。在DataSourceTransactionManager的doBegin()方法會首先檢查傳入的transaction以提取必要信息判斷之前是否存在綁定的connection信息。如果沒有,則從DataSource中獲取新的connection,然后將其AutoCoiranit狀態(tài)改為false,并綁定到TransactionSynchronizationManager。當然,這期間也會涉及事務(wù)定義的應(yīng)用以及條件檢查等邏輯。在所有一切搞定之后,newTransactionStatus會創(chuàng)建一個包含definition、transaction object以及掛起的事務(wù)信息和其他狀態(tài)信息的DefaultTransactionStatus 實例并返回。

如果definition定義的傳播行為是PROPAGATIONJNESTED,根據(jù)情況創(chuàng)建嵌套事務(wù),如通過Savepoint或者JTA的TransactionManager.如下:


在這種情況下,會首先通過isNestedTransactionAllowed ()方法檢查AbstractPlatform-TransactionManager的nestedTransactionAllowed屬性狀態(tài)。如果允許嵌套事務(wù),那么還得分兩種情況處理。對于DataSourceTransactionManager來說,因為它支持使用Savepoint創(chuàng)建嵌套事務(wù),所以,會使用Transactionstatus創(chuàng)建相應(yīng)的Savepoint并返回。而JtaTransactionManager則要依賴于具體JTA產(chǎn)品的TransactionManager提供嵌套事務(wù)支持。

useSavepointForNestedTransaction()方法默認返回true,即默認使用Savepoint創(chuàng)建嵌套事務(wù)。如果具體子類不支持使用Savepoint創(chuàng)建嵌套事務(wù),則需要覆寫該方法,如JtaTransactionManager。

(b)如果isExistingTransaction (transaction)方法返回false.即不存在當前事務(wù)的情況下。

當definition中定義的傳播行為是PROPAGATION_MANDATORY的時候,拋出異常.因為不存在當 前事務(wù),所以根據(jù)PROPAGATION-MANDATORY的語義,理當如此.

當definition中定義的傳播行為是PROPAGATION_REQUIRED? PROPAGATION_REQUIRES_NEW或者PROPAGATION_NESTED的時候,開啟新的事務(wù).如下:


之所以在doBegin之前先調(diào)用傳入null的suspend()方法,是因為考慮到如果有注冊Synchronization. 需要暫時將這些與將要開啟的新事務(wù)無關(guān)的Synchronization先放一邊。

剩下的其他情況,則返回不包含任何transaction object的Transactionstatus,這種情況下雖然是空的事務(wù),但有可能需要處理在事務(wù)過程中相關(guān)的Synchronization。

從getTransaction (TransactionDefinition)的邏輯可以看出,AbstractPlat formTran- sactionManager更多關(guān)注的是事務(wù)處理過程中的總體邏輯,而跟具體事務(wù)資源相關(guān)的處理則交給了具體的子類來實現(xiàn)。

2.2? 事務(wù)處理的完成有兩種情況,即回滾事務(wù)或者提交事務(wù),AbstractPlatformTransactionManager提供的rollback (Transactionstatus)和commit (Transactionstatus)兩個模板方法,分別對應(yīng)這兩種情況下的處理。因為事務(wù)提交過程中可能需要處理回滾邏輯,我們不妨以commit (Transactionstatus)的實現(xiàn)流程看一下AbstractPlatformTransactionManager 是如何處理事務(wù)完成的。

(1)因為在事務(wù)處理過程中,我們可以通過Transactionstatus的setRollbackOnly ()方法標記 事務(wù)回滾,所以,commit (Transactionstatus)在具體提交事務(wù)之前會檢查rollBackOnly狀態(tài)。如果該狀態(tài)被設(shè)置,那么轉(zhuǎn)而執(zhí)行事務(wù)的回滾操作。


rollback (Transactionstatus)的邏輯主要包含如下3點。

□回滾事務(wù)。這里的回滾事務(wù)又可分為如下3種情況。

■如果是嵌套事務(wù),則通過Transactionstatus釋放Savepoint。

■如果Transactionstatus表示當前事務(wù)是一個新的事務(wù),則調(diào)用子類的doRollback (Transactionstatus)方法真正的回滾事務(wù)。doRollback(Transactionstatus)是抽象方法,具體子類必須實現(xiàn)它。DataSourceTransactionManager在實現(xiàn)該方法的時候,無疑是調(diào)用connection.rollback()。HibernateTransactionManager會通過它Session上的Transaction 的rollback()方法回滾事務(wù)。其他子類對doRollback (TransactionStatus) 的實現(xiàn)邏輯依此類推。

■如果當前存在事務(wù),并且rollbackOnly狀態(tài)被設(shè)置,則調(diào)用由子類實現(xiàn)的doSet- RollbackOnly (Transactionstatus)方法,各子類實現(xiàn)通常會將當前的transaction object 的狀態(tài)設(shè)置為rollBackOnly。

□觸發(fā)Synchronization 事件。

回滾時觸發(fā)的事件比提交時觸發(fā)的事件要少,只有triggerBeforeCompletion (status)和triggerAfterCompletion。

□清理事務(wù)資源。如下所述。

■設(shè)置Transactionstatus 中的completed 為完成狀態(tài)。

■清理與當前事務(wù)相關(guān)的Synchronization。

■調(diào)用doCleanupAfterCompletion() 放事務(wù)資源,并解除到Transaction SynchronizationManager的資源綁定。對于DataSourceTransactionManager來說,是關(guān)閉數(shù)據(jù)庫連接,然后解除對Datasource對應(yīng)資源的綁定。

■如果之前有掛起的事務(wù),恢復掛起的事務(wù)。

(2)如果rollBackOnly狀態(tài)沒被設(shè)置則執(zhí)行正常的事務(wù)提交操作。

commit (TransactionStatus)方法的其他邏輯與rollback (Transactionstatus)方法基本相似,只是幾個具體操作有所差別,如下所述。

□回滾事務(wù)現(xiàn)在變成是提交事務(wù)。提交事務(wù)的時候,也會涉及如下幾種情況。

■決定是否提前檢測全局的rollBackOnly標志。如果最外層事務(wù)己經(jīng)被標記為rollBackOnly 并且failEarlyOnGlobalRollbackOnly為 true,則拋出異常。

■如果提交事務(wù)之前發(fā)現(xiàn)Transactionstatus持有Savepoint,則釋放它。這實際上是在處理恢套事務(wù)的提交。

■如果Transactionstatus表示要提交的事務(wù)是一個新的事務(wù),則調(diào)用子類的doCoimit (TransactionStatus)方法實現(xiàn)提交事務(wù)。doConunit (Transactionstatus)也是Abstract Plat formTransact ionManager 公開給子類實現(xiàn)的抽象方法,子類必須實現(xiàn)該方法。對于DataSourceTransactionManager來說,因為事務(wù)的提交由Connection決定,所以會直接調(diào)用connection. commit ()提交事務(wù)。其他的子類也會使用自身的局部事務(wù)API在該方法中實現(xiàn)事務(wù)的提交。

□需要觸發(fā)Synchronization相關(guān)事件。不過,觸發(fā)的事件比rolIback (TransactionStatus)中的要多,包括triggerBeforeCoiranit() triggerBeforeCompletion() > triggerAfterCommit ()和triggerAfterCompletion()

□ 如果AbstractplatformTransactionManager 的rollbackOnCommitFailure 狀態(tài)被設(shè)置為true,則表示如果在事務(wù)提交過程中出現(xiàn)異常,需要回滾事務(wù)。所以,當commit (Transactionstatus) 方法捕獲相應(yīng)異常,并且檢測到該字段被設(shè)置的時候,需要回滾事務(wù)。rollbackOnConunitFailure的默認值是false,表示即使提交過程中出現(xiàn)異常,也不回滾事務(wù)。

□既然commit (Transactionstatus)與rolIback(TransactionStatus)~~樣,都是意味著事務(wù)的完成,那么也需要在最后進行事務(wù)資源清理的工作,具體內(nèi)容可以參照rollback (Transactionstatus)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容