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...
微信公众号:
技术交流群: