概述(Java doc)

该注解开启spring的注解驱动事务管理功能,通常标注在@Configuration类上面用于开启命令式事务管理或响应式事务管理。

@Configuration
@EnableTransactionManagement
public class AppConfig { @Bean
public FooRepository fooRepository() {
// configure and return a class having @Transactional methods
return new JdbcFooRepository(dataSource());
} @Bean
public DataSource dataSource() {
// configure and return the necessary JDBC DataSource
} @Bean
public PlatformTransactionManager txManager() {
return new DataSourceTransactionManager(dataSource());
}
}

The example above can be compared to the following Spring XML configuration:

<beans>
<tx:annotation-driven/> <bean id="fooRepository" class="com.foo.JdbcFooRepository">
<constructor-arg ref="dataSource"/>
</bean> <bean id="dataSource" class="com.vendor.VendorDataSource"/> <bean id="transactionManager" class="org.sfwk...DataSourceTransactionManager">
<constructor-arg ref="dataSource"/>
</bean>
</beans>

添加该注解之后,spring-tx会注册必要的spring组件,这些组件支持注解驱动的事务管理,例如TransactionInterceptor和基于proxy(jdk/cglib)或aspectJ的advice,当调用@Transactional标注的方法时,这些advice将通过拦截器被调用。

注解属性

proxyTargetClass

boolean proxyTargetClass() default false;

设置为true时,创建基于子类的(CGLIB)代理。设置为false时,使用JDK Proxy创建代理。默认值为false。

该属性仅在mode属性设置为AdviceMode.PROXY时生效。

将此属性设置为true将影响所有需要代理的spring bean,而不仅仅是那些用@Transactional标记的bean。

例如,标记有@Async注解bean将同时升级为子类(CGLIB)代理,这个特性实际上没有负面影响,除非明确期望使用某种类型的代理。

mode

/**
* PROXY: JDK/CGLIB proxy-based advice
* ASPECTJ: AspectJ weaving-based advice
*/
AdviceMode mode() default AdviceMode.PROXY;

指明使用哪种代理方式嵌入事务通知。

默认AdviceMode.PROXY模式。

PROXY模式只允许通过代理对象调用。同一个类中的本地调用(即this.方法名方式)不能被拦截,本地调用时Transactional注解不会生效,因为spring aop在拦截逻辑执行之后使用原始bean对象调用目标方法,所以this.方法名方式调用会使Transactional注解失效。如果要解决这个问题,可以考虑将其切换到AdviceMode.ASPECTJ。

如果设置为AdviceMode.ASPECTJ模式,proxyTargetClass属性的值将被忽略。在这种情况下,需要依赖spring-aspects模块,该模块又依赖了AspectJ,AspectJ会在编译或加载时将事务拦截逻辑应用到@Transactional标记的类。在这种情况下没有代理,本地调用也将被拦截。

order

// Integer.MAX_VALUE
int order() default Ordered.LOWEST_PRECEDENCE;

指示在特定joinpoint应用多个通知时执行事务通知的顺序。

EnableTransactionManagement源码

@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement { boolean proxyTargetClass() default false; AdviceMode mode() default AdviceMode.PROXY; int order() default Ordered.LOWEST_PRECEDENCE;
}

TransactionManagementConfigurationSelector

public class TransactionManagementConfigurationSelector
extends AdviceModeImportSelector<EnableTransactionManagement> { @Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
} private String determineTransactionAspectClass() {
return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
}
}

PROXY模式

EnableTransactionManagement注解的mode属性设置为PROXY模式(默认)时,会Import两个组件:

  • AutoProxyRegistrar
  • ProxyTransactionManagementConfiguration

AutoProxyRegistrar

Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
if (mode == AdviceMode.PROXY) {
// 注册InfrastructureAdvisorAutoProxyCreator组件
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
// 设置proxyTargetClass为true
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}

AutoProxyRegistrar会向容器注册InfrastructureAdvisorAutoProxyCreator组件,InfrastructureAdvisorAutoProxyCreator继承了AbstractAutoProxyCreator,用于创建Advisor代理,但是它只考虑基础架构Advisor bean,会忽略@Aspect组件。

若需要支持@Aspect组件,需要使用@EnableAspectJAutoProxy注解开启AspectJ支持,EnableAspectJAutoProxy注解会注册AnnotationAwareAspectJAutoProxyCreator组件,AnnotationAwareAspectJAutoProxyCreator也继承了AbstractAutoProxyCreator,支持Advisor和@Aspect组件。这个内容在之前的AOP源码分析中记录过,此处不再展开分析。

参考AOP源码分析:

https://blog.csdn.net/xuguofeng2016/article/details/128114972

AnnotationAwareAspectJAutoProxyCreator的优先级比InfrastructureAdvisorAutoProxyCreator高,所以当同时注册时,会使用AnnotationAwareAspectJAutoProxyCreator作为Advisor代理创建器。

继承关系:

ProxyTransactionManagementConfiguration

注入事务通知相关组件:

  • BeanFactoryTransactionAttributeSourceAdvisor - 实现了PointcutAdvisor接口

  • TransactionInterceptor - 实现了MethodInterceptor接口

Advisor、Advice、Pointcut是spring aop的三组件,aop中已重点分析过,此处不再记录。

ASPECTJ模式

如果EnableTransactionManagement注解的mode属性设置为ASPECTJ模式,会导入AspectJTransactionManagementConfiguration组件。

该模式需要依赖spring-aspects模块。

AspectJTransactionManagementConfiguration

org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration

@Configuration class that registers the Spring infrastructure beans necessary to enable AspectJ-based annotation-driven transaction management for Spring's own org.springframework.transaction.annotation.Transactional annotation.

这个类会装配AnnotationTransactionAspect对象,AnnotationTransactionAspect是一个原生AspectJ组件,该组件使用原生AspectJ在类加载阶段为目标方法嵌入事务拦截逻辑以实现事务管理。

在启动时需要添加以下参数:

-javaagent:path/to/aspectjweaver-${version}.jar

AspectJ参考资料

https://javadoop.com/post/aspectj

https://www.eclipse.org/aspectj/docs.php

spring-transaction源码分析(2)EnableTransactionManagement注解的更多相关文章

  1. Spring Ioc源码分析系列--@Autowired注解的实现原理

    Spring Ioc源码分析系列--@Autowired注解的实现原理 前言 前面系列文章分析了一把Spring Ioc的源码,是不是云里雾里,感觉并没有跟实际开发搭上半毛钱关系?看了一遍下来,对我的 ...

  2. 精尽Spring Boot源码分析 - 剖析 @SpringBootApplication 注解

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  3. spring transaction源码分析--事务架构

    1. 引言  事务特性 事务是并发控制的单元,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位.通过事务将逻辑相关的一组操作绑定在一起,以便服务器 保持数据的完整性.事 ...

  4. 【Spring Boot源码分析】@EnableAutoConfiguration注解(一)@AutoConfigurationImportSelector注解的处理

    Java及Spring Boot新手,首次尝试源码分析,欢迎指正! 一.概述 @EnableAutoConfiguration注解是Spring Boot中配置自动装载的总开关.本文将从@Enable ...

  5. 精尽Spring Boot源码分析 - 文章导读

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  6. Spring Ioc源码分析系列--Bean实例化过程(二)

    Spring Ioc源码分析系列--Bean实例化过程(二) 前言 上篇文章Spring Ioc源码分析系列--Bean实例化过程(一)简单分析了getBean()方法,还记得分析了什么吗?不记得了才 ...

  7. Spring Ioc源码分析系列--自动注入循环依赖的处理

    Spring Ioc源码分析系列--自动注入循环依赖的处理 前言 前面的文章Spring Ioc源码分析系列--Bean实例化过程(二)在讲解到Spring创建bean出现循环依赖的时候并没有深入去分 ...

  8. Spring IoC 源码分析 (基于注解) 之 包扫描

    在上篇文章Spring IoC 源码分析 (基于注解) 一我们分析到,我们通过AnnotationConfigApplicationContext类传入一个包路径启动Spring之后,会首先初始化包扫 ...

  9. 精尽Spring Boot源码分析 - @ConfigurationProperties 注解的实现

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  10. [心得体会]spring事务源码分析

    spring事务源码分析 1. 事务的初始化注册(从 @EnableTransactionManagement 开始) @Import(TransactionManagementConfigurati ...

随机推荐

  1. 【2016】开机出现 system32\config\system,代码:0xc00000e9解决方法

    这是16年刚工作时写的笔记,也带来这里做个记录吧.实际工作这几年里也时不时会遇到,大多数和非正常关机有关系 今天早上,就在刚才,一个同事的电脑开不了机了,开机提示的是system32\config\s ...

  2. jclasslib的安装

    双击安装包打开后点击下一步,然后选择安装的路径. 默认路径,如果c盘有空间不建议更改路径,然后再次点击下一步 依然选择下一步 最后点击完成即可完成安装.现在可以使用啦 注:如果需要安装包,请点击下面链 ...

  3. STM32CubeMX教程4 EXTI 按键外部中断

    1.准备材料 开发板(STM32F407G-DISC1) ST-LINK/V2驱动 STM32CubeMX软件(Version 6.10.0) keil µVision5 IDE(MDK-Arm) 2 ...

  4. Navicat Premium多用户破解方法 12以上版本

    https://www.cnblogs.com/cgqplus/p/15267306.html 本文不提供注册机或者破解工具,本论坛多的是,搜索一下就好了. 本方法适用于多用户环境下使用,比如在服务器 ...

  5. 【Azure APIM】APIM 策略语句如何来设置多个Cookie值让浏览器保存

    问题描述 在APIM的 <return-response> 策略中,设置Cookie值,因为需要设置多个Cookie值,使用下面两种方式都只能保存一个Cookie值: 方式一:把多个coo ...

  6. JavaFx之WebView(二十五)

    JavaFx之WebView(二十五) jfx的web引擎已经几百年没更新,早就放弃了,写写demo还是不错.jdk8u202还能跑vue 3.0项目 import javafx.applicatio ...

  7. Java 插入、隐藏/显示、删除Excel行或列

    概述 操作Excel工作表时,对表格中的行或列数据可执行,包括插入.隐藏.显示.删除等在内的多种操作需求,本文将通过Java代码示例演示每种操作的具体实现方法.文中方法使用了Java Excel类库( ...

  8. 带你认识一下多模态对比语言图像预训练CLIP

    本文分享自华为云社区<多模态对比语言图像预训练CLIP:打破语言与视觉的界限>,作者:汀丶. 一种基于多模态(图像.文本)对比训练的神经网络.它可以在给定图像的情况下,使用自然语言来预测最 ...

  9. DevOps敏捷60问,一定有你想了解的问题

    摘要:问题覆盖了规划设计.开发集成.测试.部署发布.运维监控等DevOps落地实践中的关键疑点与难点. "DevOps的价值是又快又好地交付软件" --<凤凰项目>的作 ...

  10. WeLink的杀手锏和远程办公软件的另一面

    摘要:看WeLink如何从内到外,为广大企业用户带来数字化办公转型上的突破? 本文分享自华为云社区<[大厂内参]第11期:WeLink的杀手锏和远程办公软件的另一面>,作者: 华为云社区精 ...