Spring核心篇章:html
Spring 5 中文解析核心篇-IoC容器之依賴關係react
Spring 5 中文解析核心篇-IoC容器之Bean做用域git
Spring 5 中文解析核心篇-IoC容器之自定義Bean性質web
Spring 5 中文解析核心篇-IoC容器之BeanDefinition繼承與容器拓展點spring
Spring 5 中文解析核心篇-IoC容器之基於註解的容器配置編程
Spring 5 中文解析核心篇-IoC容器之類路徑掃描和組件管理api
Spring 5 中文解析核心篇-IoC容器之JSR330標準註解數組
Spring 5 中文解析核心篇-IoC容器之基於Java容器配置微信
Spring 5 中文解析核心篇-IoC容器之Environment抽象
Spring 5 中文解析核心篇-IoC容器之ApplicationContext與BeanFactory
Spring 5 中文解析核心篇-IoC容器之Resources
Spring 5 中文解析核心篇-IoC容器之數據校驗、數據綁定和類型轉換
Spring 5 中文解析核心篇-IoC容器之SpEL表達式
Spring 5 中文解析核心篇-IoC容器之AOP編程(上)")
Spring 5 中文解析核心篇-IoC容器之AOP編程(下)")
Spring 5 中文解析核心篇-IoC容器之Spring AOP API
Spring測試篇章:
Spring 5 中文解析核心篇-集成測試之概要和集成測試註解
Spring 5 中文解析核心篇-集成測試之TestContext(上)")
Spring 5 中文解析核心篇-集成測試之TestContext(中)")
Spring 5 中文解析測試篇-集成測試之TestContext(下)")
Spring 5 中文解析測試篇-Spring MVC測試框架
Spring 5 中文解析測試篇-WebTestClient
Spring存儲篇章:
Spring 5 中文解析數據存儲篇-Spring框架的事物支持模型的優點
[Spring 5 中文解析數據存儲篇-事務同步和聲明式事物管理
](https://mp.weixin.qq.com/s?__...
[Spring 5 中文解析數據存儲篇-@Transactional使用
](https://mp.weixin.qq.com/s?__...
完整電子書地址
除了基於XML的聲明式方法進行事務配置外,還可使用基於註解的方法。直接在Java源代碼中聲明事務語義會使聲明更加接近受影響的代碼。不存在過多耦合的風險,由於本來打算以事務方式使用的代碼幾乎老是以這種方式部署。
還支持使用標準的javax.transaction.Transactional
註解來替代Spring本身的註解。請參閱JTA 1.2
文檔以獲取更多詳細信息。
使用@Transactional
註解提供的易用性將經過一個示例獲得最好的說明,下面的示例對此進行了說明。考慮如下類定義:
// the service class that we want to make transactional @Transactional public class DefaultFooService implements FooService { Foo getFoo(String fooName) { // ... } Foo getFoo(String fooName, String barName) { // ... } void insertFoo(Foo foo) { // ... } void updateFoo(Foo foo) { // ... } }
在上面的類級別使用,註解表示聲明類(及其子類)的全部方法的默認值。另外,每種方法均可以單獨註解。注意,類級別的註解不適用於類層次結構中的祖先類。在這種狀況下,須要在本地從新聲明方法,以參與子類級別的註解。
當將一個以上的POJO類在Spring上下文中定義爲bean時,能夠經過@Configuration
類中的@EnableTransactionManagement
註解使bean實例具備事務性。有關完整的詳細信息,請參見javadoc。
在XML配置中,<tx:annotation-driven/>
標籤提供了相似的便利操做:
<!-- from the file 'context.xml' --> <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- this is the service object that we want to make transactional --> <bean id="fooService" class="x.y.service.DefaultFooService"/> <!-- enable the configuration of transactional behavior based on annotations --> <tx:annotation-driven transaction-manager="txManager"/><!-- a TransactionManager is still required --> //1 <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- (this dependency is defined somewhere else) --> <property name="dataSource" ref="dataSource"/> </bean> <!-- other <bean/> definitions here --> </beans>
若是要鏈接的TransactionManager
的bean名稱具備名稱transactionManager
,則能夠在<tx:annotation-driven/>
標籤中省略transaction-manager
屬性。若是要依賴注入的TransactionManager
bean具備其餘名稱,則必須使用transaction-manager
屬性,如上例所示。
相對於命令式編程,響應式事務方法使用響應式返回類型,以下清單所示:
// the reactive service class that we want to make transactional @Transactional public class DefaultFooService implements FooService { Publisher<Foo> getFoo(String fooName) { // ... } Mono<Foo> getFoo(String fooName, String barName) { // ... } Mono<Void> insertFoo(Foo foo) { // ... } Mono<Void> updateFoo(Foo foo) { // ... } }
請注意,對於返回的Publisher
,在響應流取消信號方面有一些特殊注意事項。有關更多詳細信息,請參見「使用TransactionOperator
」下的「取消信號」部分。
方法可見性和@Transactional使用代理時,應僅將
@Transactional
註解應用於具備公共可見性的方法。若是使用@Transactional
註解對protected
、private
或程序包可見的方法進行註解,則不會引起任何錯誤,可是<u>帶註解的方法不會顯示已配置的事務設置</u>。若是須要註解非公共方法,請考慮使用AspectJ
(稍後描述)。
你能夠將@Transactional
註解應用於接口定義、接口上的方法、類定義或類上的公共方法。可是,僅@Transactional
註解的存在不足以激活事務行爲。 @Transactional
註解僅僅是元數據,能夠被某些支持@Transactional
的運行時基礎結構使用,而且可使用元數據來配置具備事務行爲的適當Bean。在前面的示例中,<tx:annotation-driven/>
元素打開事務行爲。
Spring團隊推薦僅使用@Transactional
註解對具體類(以及具體類的方法)進行註解,而不是對接口進行註解。你固然能夠在接口(或接口方法)上放置@Transactional
註解,但這僅在你使用基於接口的代理時才能夠達到預期。Java註解不能從接口繼承的事實意味着,若是你使用基於類的代理(proxy-target-class="true"
)或基於編織的切面(mode =「aspectj」
),則事務設置不會由代理和編織基礎結構識別,而且該對象未包裝在事務代理中。在代理模式(默認)下,僅攔截經過代理傳入的外部方法調用。這意味着即便調用的方法標記有
@Transactional
,自調用(其實是目標對象中的方法調用目標對象的另外一種方法)也不會在運行時使用實際事務(譯者:調用實例自身的方法就是自調用)。另外,必須徹底初始化代理才能提供預期的行爲,所以你不該在初始化代碼(即@PostConstruct
)中依賴此功能。
若是指望自調用也與事務包裝在一塊兒,請考慮使用AspectJ
模式(請參見下表的mode
屬性)。在這種狀況下,首先沒有代理。而是編織目標類(即,修改其字節碼)以將@Transactional
轉換爲任何方法上的運行時行爲。
XML屬性 | 註解屬性 | 默認值 | 描述 |
---|---|---|---|
transaction-manager |
N/A (查看 Transaction-ManagementConfigurer -javadoc) |
transactionManager |
要使用的事務管理器的名稱。如上例所示,僅當事務管理器的名稱不是transactionManager 時才須要。 |
mode |
mode |
proxy |
默認模式(代理)經過使用Spring的AOP框架來處理帶註解的bean(遵循代理語義,如前所述,僅適用於經過代理傳入的方法調用)。替代模式(aspectj )則將受影響的類與Spring的AspectJ 事務切面進行編織,修改目標類字節碼以應用於任何類型的方法調用。AspectJ 編織須要在類路徑中使用spring-aspects.jar 並啓用加載時編織(或編譯時編織)。(有關如何設置加載時編織的詳細信息,請參見Spring配置。) |
proxy-target-class |
proxyTargetClass |
false |
僅適用於代理模式。控制爲使用@Transactional 註解註釋的類建立哪一種類型的事務代理。若是proxy-target-class 屬性設置爲true ,則將建立基於類的代理。若是proxy-target-class 爲false 或省略了屬性,則將建立基於標準JDK接口的代理。(有關不一樣代理類型的詳細檢查,請參見代理機制。) |
order |
order |
Ordered.LOWEST_PRECEDENCE |
定義應用於帶@Transactional 註解的bean的事務通知的順序。(有關AOP通知排序相關規則的更多信息,請參見通知順序。)沒有指定的順序意味着AOP子系統肯定通知的順序。 |
處理@Transactional
註解的默認通知模式是代理,它僅容許經過代理攔截調用。同一類內的本地調用沒法以這種方式被攔截(自調用)。對於更高級的攔截模式,請考慮結合編譯時或加載時編織切換到Aspectj
模式。
proxy-target-class
屬性控制爲使用@Transactional
註解註釋的類建立哪一種類型的事務代理。若是proxy-target-class
設置爲true
,則將建立基於類的代理。若是proxy-target-class
爲false
或省略了屬性,則將建立基於標準JDK接口的代理。(有關不一樣代理類型的討論,請參見core.html。)
@EnableTransactionManagement
和<tx:annotation-driven/>
僅在定義它們的相同應用程序上下文中的bean上查找@Transactional
。這意味着,若是將註解驅動的配置放在DispatcherServlet
的WebApplicationContext
中,它將僅在控制器而不是服務中檢查@Transactional
bean。有關更多信息,請參見MVC。
在評估方法的事務設置時,最派生的位置優先(譯者:範圍最小的優先級越高,例如:類和方法配置時方法優先級更高)。在下面的示例中,DefaultFooService
類在類級別使用只讀事務的設置進行註解,可是同一類中updateFoo(Foo)
方法上的@Transactional
註解優先於定義的事務設置在類級別上。
@Transactional(readOnly = true) public class DefaultFooService implements FooService { public Foo getFoo(String fooName) { // ... } // these settings have precedence for this method @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) public void updateFoo(Foo foo) { // ... } }
@Transactional
設置
@Transactional
註解是元數據,它指定接口、類或方法必須具備事務語義(例如,在調用此方法時啓動一個全新的只讀事務、暫停任何現有事務
)。默認的@Transactional
設置以下:
PROPAGATION_REQUIRED
。ISOLATION_DEFAULT
。RuntimeException
都會觸發回滾,而任何檢測的Exception
都不會觸發。你能夠更改這些默認設置。下表總結了@Transactional
註解的各類屬性:
屬性 | 類型 | 描述 |
---|---|---|
value | String |
可選的限定符,指定要使用的事務管理器。 |
propagation | enum : Propagation |
可選的傳播設置。 |
isolation |
enum : Isolation |
可選的隔離級別。僅適用於REQUIRED 或REQUIRES_NEW 的傳播值。 |
timeout |
int (以秒爲單位) |
可選的事務超時。僅適用於REQUIRED 或REQUIRES_NEW 的傳播值。 |
readOnly |
boolean |
讀寫與只讀事務。僅適用於REQUIRED 或REQUIRES_NEW 的值。 |
rollbackFor |
Class對象數組,必須從Throwable 派生。 |
必須引發回滾的異常類的可選數組。 |
rollbackForClassName |
類名數組。這些類必須從Throwable 派生。 |
必須引發回滾的異常類名稱的可選數組。 |
noRollbackFor |
Class對象數組,必須從Throwable 派生。 |
不能致使回滾的異常類的可選數組。 |
noRollbackForClassName |
字符串類名稱的數組,必須從Throwable 派生。 |
不能引發回滾的異常類名稱的可選數組。 |
當前,你沒法對事務名稱進行顯式控制,其中「名稱」是指顯示在事務監視器(若是適用)(例如,WebLogic
的事務監視器)和日誌輸出中的事務名稱。對於聲明式事務,事務名稱始終是全限定類名稱
+'.' +通知類的方法名稱
。例如,若是BusinessService
類的handlePayment(..)
方法啓動了事務,則事務的名稱將爲:com.example.BusinessService.handlePayment
。
具備@Transactional的多個事務管理器
大多數Spring應用程序僅須要一個事務管理器,可是在某些狀況下,你可能須要在一個應用程序中使用多個獨立的事務管理器。你可使用@Transactional
註解的value
或transactionManager
屬性來選擇指定要使用的TransactionManager
。這能夠是事務管理器bean的bean名稱或限定符值。例如,使用限定符表示法,能夠在應用程序上下文中將如下Java代碼與如下事務管理器bean聲明進行組合:
public class TransactionalService { @Transactional("order") public void setSomething(String name) { ... } @Transactional("account") public void doSomething() { ... } @Transactional("reactive-account") public Mono<Void> doSomethingReactive() { ... } }
如下清單顯示了bean聲明:
<tx:annotation-driven/> <bean id="transactionManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> ... <qualifier value="order"/> </bean> <bean id="transactionManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> ... <qualifier value="account"/> </bean> <bean id="transactionManager3" class="org.springframework.data.r2dbc.connectionfactory.R2dbcTransactionManager"> ... <qualifier value="reactive-account"/> </bean> </tx:annotation-driven>
在這種狀況下,TransactionalService
上的各個方法在單獨的事務管理器下運行,並根據order
、account
和reactive-account
限定符進行區分。若是未找到特別限定的TransactionManager
bean,則仍使用默認的<tx:annotation-driven>
目標bean名稱transactionManager
。
參考代碼:
org.liyong.dataaccess.starter.QualifierAnnotationTransactionManagerIocContainer
自定義組合的註解
若是你發如今許多不一樣的方法上將@Transactional
重複使用相同的屬性,則Spring的元註解支持可以讓你爲特定用例定義自定義的註解。例如,考慮如下註解定義:
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Transactional("order") public @interface OrderTx { } @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Transactional("account") public @interface AccountTx { }
前面的註解使咱們能夠按照上一節的內容編寫示例,以下所示:
public class TransactionalService { @OrderTx public void setSomething(String name) { // ... } @AccountTx public void doSomething() { // ... } }
在前面的示例中,咱們使用了語法來定義事務管理器限定符,可是咱們還能夠包括傳播行爲,回滾規則、超時和其餘功能。
參考代碼:
org.liyong.dataaccess.starter.CustomAnnotationTransactionManagerIocContainer
我的從事金融行業,就任過易極付、思建科技、某網約車平臺等重慶一流技術團隊,目前就任於某銀行負責統一支付系統建設。自身對金融行業有強烈的愛好。同時也實踐大數據、數據存儲、自動化集成和部署、分佈式微服務、響應式編程、人工智能等領域。同時也熱衷於技術分享創立公衆號和博客站點對知識體系進行分享。關注公衆號: 青年IT男 獲取最新技術文章推送!
博客地址: http://youngitman.tech
CSDN: https://blog.csdn.net/liyong1...
微信公衆號:
技術交流羣: