spring声明式事务@Transactional底层工作原理

目录
  • 引言
  • 工作机制简述
  • 事务AOP核心类释义
    • @Transactional
    • TransactionAttribute
    • SpringTransactionAnnotationParser
    • AnnotationTransactionAttributeSource
    • TransactionAttributeSourcePointcut
    • TransactionInterceptor
    • BeanFactoryTransactionAttributeSourceAdvisor
    • ProxyTransactionManagementConfiguration
  • 事务抽象核心类释义
    • PlatformTransactionManager
    • TransactionStatus
    • TransactionDefinition
  • 结语

引言

写这篇博文有个来由,是为了解决博主遇到的多数据源的事务问题(用不了JTA),所以深入到spring-tx的源码去学习了一番,非常有收获,最后博主的分布式事务问题也迎刃而解了,这个文章算个开篇,关于如何处理多数据源事务,待下文分解。本文涉及到的技术包含spring aop的使用、spring bean生命周期等,如果能够真正理解Transactional的工作原理,对排查事务相关的问题有非常大的帮助。

spring-tx版本:5.0.2

工作机制简述

先来看一张官方的事务简图:

spring定义了@Transactional注解,基于AbstractBeanFactoryPointcutAdvisor、StaticMethodMatcherPointcut、MethodInterceptor的aop编程模式,增强了添加@Transactional注解的方法。同时抽象了事务行为为PlatformTransactionManager(事务管理器)、TransactionStatus(事务状态)、TransactionDefinition(事务定义)等形态。最终将事务的开启、提交、回滚等逻辑嵌入到被增强的方法的前后,完成统一的事务模型管理。

事务AOP核心类释义

@Transactional

事务注解,用于定位aop的切入点,事务注解里包含了完整事务的所有基本属性,常见的属性如:

transactionManager:事务管理器

propagation:传播行为定义,枚举类型,是spring独有的事务行为设计,默认为PROPAGATION_REQUIRED(支持当前事务,不存在则新建)

isolation:隔离级别,对应数据库的隔离级别实现,mysql默认的隔离级别是 read-committed

timeout:超时时间,默认使用数据库的超时,mysql默认的事务等待超时为5分钟

readOnly:是否只读,默认是false

rollbackFor:异常回滚列表,默认的是RuntimeException异常回滚

TransactionAttribute

事务属性抽象接口类,承载了@Transactional注解里的所有属性,实现类的继承关系如下类结构图,这个实例在被注解解析器创建好后,会在事务上下文中传递

SpringTransactionAnnotationParser

见名知意,这个类是spring的事务注解解析器,实现自TransactionAnnotationParser接口,是spring管理的事务解析器,用于解析@Transactional注解,将注解里的属性设置到TransactionAttribute的实现类属性里。除了这个,另还有两个实现,分别是JTA事务注解解析器,和EJB事务注解管理解析器,区别是解析的注解不同,spring是@Transactional,jta是javax.transaction.Transactional,EJB是javax.ejb.TransactionAttribute。这个地方应用和apache dubbo2.7.x版本解析dubbo的@service注解是一样一样的。关键代码如下,通过AnnotatedElementUtils类,这个类在spring-core包下,找到注解属性集AnnotationAttributes,如果不为空,则包装成事务属性集返回

@Override
	@Nullable
	public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
		AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
				element, Transactional.class, false, false);
		if (attributes != null) {
			return parseTransactionAnnotation(attributes);
		}
		else {
			return null;
		}
	}

AnnotationTransactionAttributeSource

见名知意,这个类是注解事务属性集的源,怎么理解呢?spring抽象了获取事务属性集的行为,而AnnotationTransactionAttributeSource正是@Transactional注解方式的事务属性集收集实现。SpringTransactionAnnotationParser就是作用于这个里面,用于发现@Transactiona注解的方法

TransactionAttributeSourcePointcut

也是见名知意,Pointcut属于aop的概念范畴,需要了解spring aop的知识才能看明白,这个就是@Transactional注解的切点,AnnotationTransactionAttributeSource作用于此,用于寻找@Transactiona注解的方法,关键代码如下:

public boolean matches(Method method, Class targetClass) {
		TransactionAttributeSource tas = getTransactionAttributeSource();
		return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
	}

TransactionInterceptor

事务的拦截器。aop编程里,有了切入点Pointcut,就要有通知advice,我们熟悉的spring aop里有前置、后置、环绕、异常等通知类型,TransactionInterceptor属于自定义通知模型实现,实现自Advice接口,类似于环绕通知,具体见类结构图,如下:

核心方法如下:

public Object invoke(MethodInvocation invocation) throws Throwable {
		// Work out the target class: may be {@code null}.
		// The TransactionAttributeSource should be passed the target class
		// as well as the method, which may be from an interface.
		Class targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
		// Adapt to TransactionAspectSupport's invokeWithinTransaction...
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}

被@Transactional注解的方法,如果被aop正确的增强了,运行的时候都会进入到这个方法里面,如果你发现事务不生效啊等等问题,可以从这里开始定位真实原因

BeanFactoryTransactionAttributeSourceAdvisor

事务增强器,用于增强添加了@Transactional注解的方法,上面提到的这些核心类,最终都作用于这里,用于寻找@Transactional注解的方法和织入事务处理逻辑

ProxyTransactionManagementConfiguration

代理事务管理的配置类,上面介绍的这些事务aop编程相关的在这个里面组合配置生效的,同时,如果你有特殊的个性化的需求,也可以自定义注册这个里面的实例。比如我嫌弃@Transactional注解太长了,想用@Tx注解。没关系,直接定义个TransactionAttributeSource实现,解析@Tx的方法,然后注册到spring的上线文中即可。代码如:

@Configuration(proxyBeanMethods = false)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
			TransactionAttributeSource transactionAttributeSource,
			TransactionInterceptor transactionInterceptor) {
		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		advisor.setTransactionAttributeSource(transactionAttributeSource);
		advisor.setAdvice(transactionInterceptor);
		if (this.enableTx != null) {
			advisor.setOrder(this.enableTx.getNumber("order"));
		}
		return advisor;
	}
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
		return new AnnotationTransactionAttributeSource();
	}
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionInterceptor transactionInterceptor(
			TransactionAttributeSource transactionAttributeSource) {
		TransactionInterceptor interceptor = new TransactionInterceptor();
		interceptor.setTransactionAttributeSource(transactionAttributeSource);
		if (this.txManager != null) {
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}
}

事务抽象核心类释义

PlatformTransactionManager

平台事务管理器,这是Spring事务基础设施中的中心接口。它定义了三个最最基本的事务方法,getTransaction获取事务,包含了事务开启的行为,commit提交事务,rollback回滚事务。代码如下:

public interface PlatformTransactionManager extends TransactionManager {
	TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException;
	void commit(TransactionStatus status) throws TransactionException;
	void rollback(TransactionStatus status) throws TransactionException;
}

在spring-tx中并没有提供真正的实现类,只提供了一个抽象派生类AbstractPlatformTransactionManager,并建议其他实现基于这个派生类,因为它预先实现了定义的传播行为并处理事务同步处理。子类必须为底层事务的特定状态实现模板方法,例如:begin、suspend、resume、commit等。我们平时常见的实现有:JpaTransactionManager、JtaTransactionManager、DataSourceTransactionManager等。事务管理器和事务aop处理的逻辑本身没有任何耦合,只需将PlatformTransactionManager实例注册到spring上下文中即可,事务拦截器会通过获取到@Transactional里的transactionManager属性去上下文中寻找事务管理器,并将其缓存起来,见TransactionAspectSupport.java里的determineTransactionManager方法

protected PlatformTransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
		// Do not attempt to lookup tx manager if no tx attributes are set
		if (txAttr == null || this.beanFactory == null) {
			return asPlatformTransactionManager(getTransactionManager());
		}
		String qualifier = txAttr.getQualifier();
		if (StringUtils.hasText(qualifier)) {
			return determineQualifiedTransactionManager(this.beanFactory, qualifier);
		}
		else if (StringUtils.hasText(this.transactionManagerBeanName)) {
			return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
		}
		else {
			PlatformTransactionManager defaultTransactionManager = asPlatformTransactionManager(getTransactionManager());
			if (defaultTransactionManager == null) {
				defaultTransactionManager = asPlatformTransactionManager(
						this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY));
				if (defaultTransactionManager == null) {
					defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class);
					this.transactionManagerCache.putIfAbsent(
							DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
				}
			}
			return defaultTransactionManager;
		}
	}

TransactionStatus

事务状态抽象,用这个类的实现来维护当前的事务状态,spring-tx里提供了默认的实现DefaultTransactionStatus。一般情况下这个不需要我们关心,它和PlatformTransactionManager是成对存在的,心细的你可能已经发现了,PlatformTransactionManager里的三个事务行为传递的就是TransactionStatus。我们知道事务aop增强了添加@Transactional的方法,在执行方法前调用PlatformTransactionManager.getTransaction开启事务,之后调用commit方法提交事务,提交事务的入参TransactionStatus就是开启事务获得的。参见TransactionAspectSupport.java里的createTransactionIfNecessary方法

TransactionDefinition

事务定义,对应了TransactionAttribute,最终通过aop得到的TransactionAttribute里的属性会被传递到TransactionDefinition里,所以TransactionDefinition里也包含了所有事务相关的属性,PlatformTransactionManager.getTransaction正是通过这个里面的属性去获取的事务。AbstractPlatformTransactionManager派生类里也是通过这个里面的属性去判断协调spring的事务传播行为的

结语

当梳理完spring-tx模块的整个结构和工作方式后,仿佛拉开了spring事务管理的面纱,很多事务的执行细节一览无余。很多事务相关的问题也就很容易解释了。比如常见的类中的方法直接调用方法事务不生效等问题,以及可以非常清晰的理解spring的传播行为的真正含义等。最后预告下,spring对于多数据源的事务处理解决方案ChainedTransactionManager

以上就是spring声明式事务@Transactional底层工作原理的详细内容,更多关于spring声明式事务@Transactional工作原理的资料请关注我们其它相关文章!

(0)

相关推荐

  • springboot中事务管理@Transactional的注意事项与使用场景

    前言:在service层的方法上使用@Transactional 即可实现处理数据库发生错误时触发事务回滚机制. 注意: Spring 基于注解的声明式事物 @Transactional 默认情况下只会对运行期异常(java.lang.RuntimeException及其子类)和 Error 进行回滚. 数据库引擎要支持事物,使用InnoDB. @Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没

  • spring的@Transactional注解用法解读

    概述 事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性. Spring Framework对事务管理提供了一致的抽象,其特点如下: 为不同的事务API提供一致的编程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Data Objects) 支持声明式事务管理,特别是基于注解的声明式事务管理,简单易用 提供比其他事务API如JTA更简单的编程式事务管

  • 基于Spring中的事务@Transactional细节与易错点、幻读

    目录 为什么要使用事务? 如何使用事务? 事务的传播带来的几种结果 两个特例 事务传播属性propagation 数据库隔离级别 1.未提交读(会有脏读的现象) 2.已提交读 3.可重复读 (有可能覆盖掉其他事务的操作) 4.串行化(没有并发操作) Spring事务隔离级别比数据库事务隔离级别多一个default ACID,事务内的一组操作具有 原子性 .一致性.隔离性.持久性. Atomicity(原子性):一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束

  • spring @Transactional 无效的解决方案

    关于@Transactional注解 一般都认为要注意以下三点 1 .在需要事务管理的地方加@Transactional 注解.@Transactional 注解可以被应用于接口定义和接口方法.类定义和类的 public 方法上 . 2 . @Transactional 注解只能应用到 public 可见度的方法上 . 如果你在 protected.private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展

  • Spring中@Transactional用法详细介绍

    Spring中@Transactional用法详细介绍 引言: 在spring中@Transactional提供一种控制事务管理的快捷手段,但是很多人都只是@Transactional简单使用,并未深入了解,其各个配置项的使用方法,本文将深入讲解各个配置项的使用. 1.  @Transactional的定义 Spring中的@Transactional基于动态代理的机制,提供了一种透明的事务管理机制,方便快捷解决在开发中碰到的问题.在现实中,实际的问题往往比我们预期的要复杂很多,这就要求对@Tr

  • spring声明式事务@Transactional底层工作原理

    目录 引言 工作机制简述 事务AOP核心类释义 @Transactional TransactionAttribute SpringTransactionAnnotationParser AnnotationTransactionAttributeSource TransactionAttributeSourcePointcut TransactionInterceptor BeanFactoryTransactionAttributeSourceAdvisor ProxyTransaction

  • spring声明式事务 @Transactional 不回滚的多种情况以及解决方案

    目录 一. spring 事务原理 问题一.@Transactional 应该加到什么地方,如果加到Controller会回滚吗? 问题二. @Transactional 注解中用不用加rollbackFor = Exception.class 这个属性值 问题三:事务调用嵌套问题具体结果如下代码: 四.总结 五. 参考链接 本文是基于springboot完成测试测试代码地址如下: https://github.com/Dr-Water/springboot-action/tree/master

  • Spring声明式事务@Transactional知识点分享

    @Transactional注解支持9个属性的设置,这里只讲解其中使用较多的三个属性:readOnly.propagation.isolation.其中propagation属性用来枚举事务的传播行为,isolation用来设置事务隔离级别,readOnly进行读写事务控制. @Service @Transactional(readOnly = true) public class AppTradeRec2Service extends BaseService { @Autowired priv

  • spring 声明式事务实现过程解析

    这篇文章主要介绍了spring 声明式事务实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 /** * 声明式事务: * * 环境搭建: * 1.导入相关依赖 * 数数据 * 3.给方法上标注 @Transactional 表示当前方法是一个事务方法: * 4. @EnableTransactionManagement 开启基于注解的事务管理功能:据源.数据库驱动.Spring-jdbc模块 * * 2.配置数据源.JdbcTempl

  • Spring声明式事务注解之@EnableTransactionManagement解析

    Spring声明式事务注解之@EnableTransactionManagement 1. 说明 @EnableTransactionManagement声明在主配置类上,表示开启声明式事务,其原理是通过@Import导入TransactionManagementConfigurationSelector组件,然后又通过TransactionManagementConfigurationSelector导入组件AutoProxyRegistrar和ProxyTransactionManageme

  • 完美解决Spring声明式事务不回滚的问题

    疑问,确实像往常一样在service上添加了注解 @Transactional,为什么查询数据库时还是发现有数据不一致的情况,想想肯定是事务没起作用,出现异常的时候数据没有回滚.于是就对相关代码进行了一番测试,结果发现一下踩进了两个坑,确实是事务未回滚导致的数据不一致. 下面总结一下经验教训: Spring事务的管理操作方法 编程式的事务管理 实际应用中很少使用 通过使用TransactionTemplate 手动管理事务 声明式的事务管理 开发中推荐使用(代码侵入最少) Spring的声明式事

  • Spring声明式事务配置使用详解

    目录 序章 准备工作 创建jdbc.properties 配置Spring的配置文件 声明式事务概念 代码讲解 配置 Spring 的配置文件 创建表 创建组件 测试无事务情况 加入事务 序章 Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作 准备工作 <dependencies> <!-- 基于Maven依赖传递性,导入spring-context依赖即可导入当前所需所有jar包 --> <dependency> <

  • spring声明式事务解析

    一.spring声明式事务 1.1 spring的事务管理器 spring没有直接管理事务,而是将管理事务的责任委托给JTA或相应的持久性机制所提供的某个特定平台的事务实现.spring容器负责事物的操作,spring容器充当切面,事务的方法称为增强处理,生成的代理对象的方法就是目标方法+增强也就是crud+事务程序员只用做crud的操作,也就是目标方法和声明哪些方法应该在事务中运行. Spring提供了许多内置事务管理器实现: DataSourceTransactionManager:位于or

  • spring声明式事务管理解析

    前沿:通过对spring事务管理有了比较深入学习,本文将不做实例,而是指定具体的类和配置文件进行讲解. 本文内容: 1.了解什么是声明式事务? 2.声明式事务管理分别有哪几种? 3.这几种事务管理之间的区别是什么? 一.什么是声明式事务? 声明式事务(declarative transaction management)是spring提供的对程序事务管理的方式之一.Spring的声明式事务就是采用声明的方式来处理事务,用在Spring配置文件中声明式的处理事务来代替代码式的处理事务.这样的好处是

  • Spring声明式事务和@Aspect的拦截顺序问题的解决

    在使用AbstractRoutingDataSource配置多数据源时,发现使用@aspect配置的DataSourceSwitchAspect总是在声明式事务之后执行,配置了Order依然不行,经过调研发现是由于两者的aop代理方式不一致导致. 在spring内部,是通过BeanPostProcessor(<spring 攻略>一书中翻译为,后处理器)来完成自动创建代理工作的.根据匹配规则的不同大致分为三种类别: 1.匹配Bean的名称自动创建匹配到的Bean的代理,实现类BeanNameA

随机推荐