Spring中的事務管理為我們做了哪些事?
相信 Java 程序員一定聽過大名鼎鼎的 Spring 框架,Spring 框架的低侵入性,模塊間的解耦,DI 機制,AOP 特性等為程序員大大降低了程序開發的難度,可以說 Spring 目前是最流行的框架技術,佔有很大一部分市場,為廣大程序員帶來巨大的便利。
今天來聊一聊 Spring 中的事務管理為我們做了些什麼事。
由於 DI 和 AOP 是整個 Spring 框架的靈魂,而且今天要講的事務管理也是基於 AOP 的,所以不明白的請先移步至:
11. Aspect Oriented Programming with Spring
先看一段老代碼:
上面代碼是一個完整事務,缺點很明顯,就是比較啰嗦。實際上要做的事情只有向資料庫中插入一條數據。如果每組 jdbc 操作都要去控制 connection,preparedStatement 的狀態,一堆的 try-catch-finally 代碼,看起來很頭疼,而且非常容易寫錯,忘記關閉 connection 也會導致資源耗盡這樣致命的錯誤。
程序員都是很懶的,這些複雜的重複率非常高的代碼最好能交給某個模版去幫忙管理,用技術幹掉重複的事情,從而能更好的專註於自己的業務代碼。
下面介紹一下 Spring 怎樣去幫助我們管理了上面這些狀態,先看一下 Spring 中聲明式事務能簡化到怎樣的程度。
1、需要配置 dataSource, transactionManager, sqlSessionFactory, MapperScannerConfigurer
2、業務邏輯中事務的入口
看上去使用 Spring 幫我們管理的事務是非常簡單的,而且業務代碼簡潔到了極致。
只要我們配置好了相應的 dataSource,transactionManager, sqlSessionFactory, MapperScannerConfigurer,
在需要事務的方法上加上註解 @Transactional 即可。
@Transactional 這個註解裡面有幾個屬性用來描述程序員需要的事務類型。
看一下源碼裡面有如下幾個屬性:
那麼 Spring 框架是怎樣做到的呢?
@Transactional 這個註解的背後有怎樣的邏輯呢?
為什麼那些複雜的狀態控制代碼,資源釋放的代碼都看不到了呢?
將一組 jdbc 操作放入同一個事務需要的幾個步驟:
- 開啟事務
- jdbc 操作
- 成功:提交事務異常:回滾事務
- 釋放資源
實際上,正是 Spring 幫助我們做了上述1,3,4三步(第2步使我們的業務代碼)。看一下之前配置的 transactionManager 以及其父類AbstractPlatformTransactionManager,AbstractPlatformTransactionManager繼承了介面 PlatformTransactionManager,而該介面中只有三個方法:
可以看出這三個方法分別對應了1)3)兩個步驟。
繼續看抽象類 AbstractPlatformTransactionManager 中的方法,AbstractPlatformTransactionManager 的方法有很多,其中有幾個方法值得注意:
看到這裡1)3)4)三步都有了方法對應。每個 public 方法又對應了以「do*」開頭各自 protected abstract 方法,這是什麼意思呢?
實際上繼承於AbstractPlatformTransactionManager 的類有很多,如DataSourceTransactionManager , JtaTransactionManager, HibernateTransactionManager 等,不管是哪一個種,總要有 getTransaction,commit,rollback的方法,所以這個三個方法在介面中,不過具體實現方式有所區別,所以具體的實現需要而且是必須在子類中完成。
AbstractPlatformTransactionManager 規定了這三個方法的調用順序,真正的細節在子類中以」do*」開頭的方法中實現,這也正是大多數抽象類的作用所在。
當然 AbstractPlatformTransactionManager 中還有很多其它方法,我們這裡只關注最重要的幾個主幹上方法,也就是介面中規定的方法以及其子類中的實現,這裡子類選取 DataSourceTransactionManager 進行代碼分析。
首先先結合時序圖看一下幾個主要方法的調用:
下面與源碼相結合,先看一下入口處,也就是 AbstractPlatformTransactionManager 中 getTransaction(TransactionStatus status) 方法:
跳轉到子類 doBegin(…) 方法中:
此時 Spring 框架已經幫我們獲取了一個 connetion,並且設置了 autoCommit 為 false。之後調用 service 中的代碼,如果一切順利 Spring 框架將繼續調用 AbstractPlatformTransactionManager 中的 commit(…) 方法,繼續看源碼:
跳轉到子類看下 doCommit(…) 方法具體做了些什麼事情:
現在事務已經提交了,如果是異常的情況,父類中調用方法 robbback(…):
跳轉到子類中看 doRollback(…) 的具體實現:
最後看一下對資源釋放的代碼,父類中 cleanupAfterCompletion(status) 方法調用了 doCleanupAfterCompletion(...):
至此 Spring 幫我們管理的事務,其主要流程和方法已經介紹完了,當然其中還有很多 private 方法和 protected 方法沒有介紹。我想只要把主幹捋清除之後,其他一些方法也很好理解了。
繞了一大圈,實際上還是繞不過開始事務,提交事務,回滾事務三件事,只是這三件事情現在由 Spring 幫助我們在背後默默做好了。
應該感謝 Spring 幫助程序員做了這些繁瑣的事情,可以讓程序員不用擔心資源泄露之類事情,專註於自己的業務邏輯代碼。同時 Spring 框架代碼規範,設計清晰也是程序員非常值得借鑒的地方。
本文作者:謝星星(點融黑幫),目前就職於點融網架構組Backend Architecture團隊,簡單務實的程序猿,寫代碼不給自己挖坑更不能留坑於他人。
本文由@點融黑幫(ID:DianrongMafia)原創發佈於知乎,未經許可,禁止轉載。
推薦閱讀:
※Spring和struts2整合詳解
※Spring Security(二) -- Spring Security的Filter
※Ribbon源碼分析系列(一)
※【spring指南系列】計劃任務