spring-transaction源码分析(2)EnableTransactionManagement注解

这篇具有很好参考价值的文章主要介绍了spring-transaction源码分析(2)EnableTransactionManagement注解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概述(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代理创建器。

继承关系:
spring-transaction源码分析(2)EnableTransactionManagement注解

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文章来源地址https://www.toymoban.com/news/detail-434892.html

到了这里,关于spring-transaction源码分析(2)EnableTransactionManagement注解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • spring @Transactional注解参数详解

    事物注解方式: @Transactional 当标于类前时, 标示类中所有方法都进行事物处理 , 例子: 当类中某些方法不需要事物时: 事物传播行为介绍: @Transactional(propagation=Propagation.REQUIRED) :如果有事务, 那么加入事务, 没有的话新建一个(默认情况下) @Transactional(propagation=Propagation.NOT_SUPPORTE

    2024年02月21日
    浏览(30)
  • Spring 源码分析(二)——GenericBeanDefinition 分析

    BeanDefinition 中存储着 Bean 的定义信息,它具有属性值、构造函数参数值以及具体实现 Bean 提供的进一步信息,在学习 Spring 的 Bean 初始化流程之前,还是非常有必要先了解一下 BeanDefinition 。 首先,本文先举一个使用 BeanDefinition 创建 Bean 的小例子: 执行结果输出: GenericBean

    2023年04月11日
    浏览(32)
  • 【spring(四)】Spring事务管理和@Transactional注解

    🌈键盘敲烂,年薪30万🌈 目录 Spring中的事务管理 问题抛出: 解决方案: @Transactional注解: rollbackFor属性: propagation属性: 应用: 📕总结 知识回顾: ❓什么是事务 事务是对数据操作的集合,它是数据操作的最小执行单位,也就是说,要么一个事务中操作全部执行完毕,

    2024年01月17日
    浏览(46)
  • Spring——事务注解@Transactional【建议收藏】

    在某些业务场景下,如果一个请求中,需要同时写入多张表的数据或者执行多条sql,为了保证操作的原子性(要么同时成功,要么同时失败),避免数据不一致的情况,我们一般都会用到事务;Spring框架下,我们经常会使用@Transactional注解来管理事务; 本篇介绍Spring的事务注

    2024年02月03日
    浏览(45)
  • Spring @Transactional事务传播机制详解

    我们日常工作中极少使用事务传播级别,单纯只是使用事务和rollbackfor抛出异常来解决事务问题,但其实我们很多时候使用的是不正确的,或者说会造成事务粒度过大,本文详解一下事务传播级别,也让自己更好地处理事务问题。 1.什么是事务传播机制? 举个栗子,方法A是一

    2024年02月14日
    浏览(41)
  • Spring源码分析(五) 事务全流程分析

    @Transactional 注解的属性信息 name 当在配置文件中有多个 TransactionManager , 可以用该属性指定选择哪个事务管理器 propagation 事务的传播行为,默认值为 REQUIRED。 isolation 事务的隔离度,默认值采用 DEFAULT。 timeout 事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完

    2024年02月07日
    浏览(34)
  • 【spring源码分析】@Conditional的使用以及分析

    @Conditional 一、基本信息 二、注解描述 三、注解源码 四、主要功能 五、最佳实践 在@Bean上使用 在@Configuration上使用 自定义组合注解 六、时序图 七、源码分析 八、注意事项 九、总结 最佳实践总结 源码分析总结 一、基本信息 转载自github,在此作为个人备份(https://blog.csdn.

    2024年01月21日
    浏览(89)
  • Spring 声明式事务 @Transactional(基本使用)

            声明式事务的实现很简单,只需要在需要事务的⽅法上添加 @Transactional 注解就可以实现了.⽆需⼿动开启事务和提交事务,进⼊⽅法时⾃动开启事务,⽅法执⾏完会⾃动提交事务,如果中途发⽣了 没有处理的异常会⾃动回滚事务.         废话不多说,直接看代码实现,

    2024年01月23日
    浏览(48)
  • Spring IOC 源码分析

    ​ IoC (Inversion of control ) 控制反转。它是一种思想不是一个技术实现。描述的是: Java 开发领域对象的创建以及管理的问题。 例如:现有类 A 依赖于类 B 。传统的开发方式 :往往是在类 A 中手动通过 new 来 new 一个 B 的对象出来使用 IoC 思想的开发方式 :不通过 ne

    2024年02月02日
    浏览(44)
  • Spring AOP 源码分析

    【阅读前提】: 需了解 AOP 注解开发流程:链接 在配置类中添加注解 @EnableAspectJAutoProxy ,便开启了 AOP (面向切面编程) 功能。此注解也是了解 AOP 源码的入口。 【1】 @EnableAspectJAutoProxy 是什么?我们进入注解,查看其源码如下:发现调用 EnableAspectJAutoProxy 类,同时使用 @

    2024年01月16日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包