Spring事務管理

Spring的統一事務模型,解決的一個核心問題,就是無論你用的是什麼數據訪問方式,Hibernate、MyBatis抑或是JDBC,你的Service層的代碼都是同樣的,不須要作任何變更。程序員

做者:光頭程序員
連接:https://zhuanlan.zhihu.com/p/59731142
來源:知乎
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。

Spring和事務的關係數據庫

  • 關係型數據庫、某些消息隊列等產品或中間件稱爲事務性資源,由於它們自己支持事務,也可以處理事務。
  • Spring很顯然不是事務性資源,可是它能夠管理事務性資源,因此Spring和事務之間是管理關係。
  • 就像Jack Ma雖然不會寫代碼,可是他卻管理者一大批會寫代碼的碼農。

Spring事務三要素ui

  • 數據源:表示具體的事務性資源,是事務的真正處理者,如MySQL等。
  • 事務管理器:像一個大管家,從總體上管理事務的處理過程,如打開、提交、回滾等。
  • 事務應用和屬性配置:像一個標識符,代表哪些方法要參與事務,如何參與事務,以及一些相關屬性如隔離級別、超時時間等。

Spring事務的註解配置線程

  • 把一個DataSource(如DruidDataSource)做爲一個@Bean註冊到Spring容器中,配置好事務性資源。
  • 把一個@EnableTransactionManagement註解放到一個@Configuration類上,配置好事務管理器,並啓用事務管理。
  • 把一個@Transactional註解放到類上或方法上,能夠設置註解的屬性,代表該方法按配置好的屬性參與到事務中。

事務註解的本質代理

  • @Transactional這個註解僅僅是一些(和事務相關的)元數據,在運行時被事務基礎設施讀取消費,並使用這些元數據來配置bean的事務行爲。
  • 大體來講具備兩方面功能,一是代表該方法要參與事務,二是配置相關屬性來定製事務的參與方式和運行行爲。

Spring聲明式事務實現原理中間件

  • 聲明式事務成爲可能,主要得益於Spring AOP。使用一個事務攔截器,在方法調用的先後/周圍進行事務性加強(advice),來驅動事務完成。

如何回滾一個事務對象

  • 就是在一個事務上下文中當前正在執行的代碼裏拋出一個異常,事務基礎設施代碼會捕獲任何未處理的異常,而且作出決定是否標記這個事務爲回滾。

默認回滾規則繼承

  • 默認只把runtime, unchecked exceptions標記爲回滾,即RuntimeException及其子類,Error默認也致使回滾。Checked exceptions默認不致使回滾。這些規則和EJB是同樣的。

如何配置回滾異常接口

  • 使用@Transactional註解的rollbackFor/rollbackForClassName屬性,能夠精確配置致使回滾的異常類型,包括checked exceptions。
  • noRollbackFor/noRollbackForClassName屬性,能夠配置不致使回滾的異常類型,當遇到這樣的未處理異常時,照樣提交相關事務。

事務註解在類/方法上隊列

  • @Transactional註解既能夠標註在類上,也能夠標註在方法上。當在類上時,默認應用到類裏的全部方法。若是此時方法上也標註了,則方法上的優先級高。

事務註解在類上的繼承性

  • @Transactional註解的做用能夠傳播到子類,即若是父類標了子類就不用標了。但倒過來就不行了。
  • 子類標了,並不會傳到父類,因此父類方法不會有事務。父類方法須要在子類中從新聲明而參與到子類上的註解,這樣纔會有事務。

事務註解在接口/類上

  • @Transactional註解能夠用在接口上,也能夠在類上。在接口上時,必須使用基於接口的代理才行,即JDK動態代理。
  • 事實是Java的註解不能從接口繼承,若是你使用基於類的代理,即CGLIB,或基於織入方面,即AspectJ,事務設置不會被代理和織入基礎設施認出來,目標對象不會被包裝到一個事務代理中。
  • Spring團隊建議註解標註在類上而非接口上。

只在public方法上生效?

  • 當採用代理來實現事務時,(注意是代理),@Transactional註解只能應用在public方法上。當標記在protected、private、package-visible方法上時,不會產生錯誤,但也不會表現出爲它指定的事務配置。能夠認爲它做爲一個普通的方法參與到一個public方法的事務中。
  • 若是想在非public方法上生效,考慮使用AspectJ(織入方式)。

目標類裏的自我調用沒有事務?

  • 在代理模式中(這是默認的),只有從外部的方法調用進入經過代理會被攔截,這意味着自我調用(實際就是,目標對象中的一個方法調用目標對象的另外一個方法)在運行時不會致使一個實際的事務,即便被調用的方法標有註解。
  • 若是你但願自我調用也使用事務來包裝,考慮使用AspectJ的方式。在這種狀況下,首先是沒有代理。相反,目標類被織入(即它的字節碼被修改)來把@Transactional加入到運行時行爲,在任何種類的方法上均可以。

事務與線程

  • 和JavaEE事務上下文同樣,Spring事務和一個線程的執行相關聯,底層是一個ThreadLocal<Map<Object, Object>>,就是每一個線程一個map,key是DataSource,value是Connection。
相關文章
相關標籤/搜索