Spring 外围篇章:
Spring 5 中文解析之外围篇 -IoC 容器
Spring 5 中文解析外围篇 -IoC 容器之依赖关系
Spring 5 中文解析外围篇 -IoC 容器之 Bean 作用域
Spring 5 中文解析外围篇 -IoC 容器之自定义 Bean 性质
Spring 5 中文解析外围篇 -IoC 容器之 BeanDefinition 继承与容器拓展点
Spring 5 中文解析外围篇 -IoC 容器之基于注解的容器配置
Spring 5 中文解析外围篇 -IoC 容器之类门路扫描和组件治理
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 测试
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>
- 使 bean 实例具备事务性的行为
如果要连贯的
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…
微信公众号:
技术交换群: