Spring声明式事务源码分析

文章目录

概要

编程式事务 :在业务代码中添加事务控制代码,这样的事务控制机制就叫做编程式事务
声明式事务:通过xml或者注解配置的⽅式达到事务控制的⽬的,叫做声明式事务

Spring的事务管理的核心接口是org.springframework.transaction.PlatformTransactionManager

java 复制代码
public interface PlatformTransactionManager {
	//  获取事务状态信息
	//	AbstractPlatformTransactionManager抽象类中
	TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;
	
	//  提交事务
	//	进入 AbstractPlatformTransactionManager.commit
	void commit(TransactionStatus status) throws TransactionException;
	
	//  回滚事务
	//	AbstractPlatformTransactionManager.rollback()
	void rollback(TransactionStatus status) throws TransactionException;

}

此接⼝是Spring的事务管理器核⼼接⼝。Spring本身并不⽀持事务实现,只是负责提供标准,应⽤底层⽀持什么样的事务,需要提供具体实现类。此处也是策略模式的具体应⽤。在Spring框架中,也为我们内置了⼀些具体策略:DataSourceTransactionManager ,HibernateTransactionManager

DataSourceTransactionManager 归根结底是横切逻辑代码,声明式事务要做的就是使⽤Aop(动态代理)来将事务控制逻辑织⼊到业务代码.

声明式事务纯注解方式使用如下:

在 Spring 的配置类上添加 @EnableTransactionManagement 注解即可

java 复制代码
@Configuration
  @EnableTransactionManagement
  public class AppConfig {
}

那么,该注解@EnableTransactionManagement具体做了哪些东西呢?

@EnableTransactionManagement

java 复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

	boolean proxyTargetClass() default false;

	AdviceMode mode() default AdviceMode.PROXY;

	
	int order() default Ordered.LOWEST_PRECEDENCE;

}

@EnableTransactionManagement 注解使⽤ @Import 标签引⼊了TransactionManagementConfigurationSelector类,这个类⼜向容器中导⼊了两个重要的组件.

AutoProxyRegistrar

AutoProxyRegistrar 类的 registerBeanDefinitions ⽅法中⼜注册了⼀个组件

进⼊ AopConfigUtils.registerAutoProxyCreatorIfNecessary ⽅法

发现最终,注册了⼀个叫做 InfrastructureAdvisorAutoProxyCreator 的 Bean,⽽这个类是

AbstractAutoProxyCreator 的⼦类,实现了 SmartInstantiationAwareBeanPostProcessor 接⼝

java 复制代码
public class InfrastructureAdvisorAutoProxyCreator extends
AbstractAdvisorAutoProxyCreator
public abstract class AbstractAdvisorAutoProxyCreator extends
AbstractAutoProxyCreator
public abstract class AbstractAutoProxyCreator extends
ProxyProcessorSupport
 implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware

它实现了SmartInstantiationAwareBeanPostProcessor,说明这是⼀个后置处理器,⽽且跟spring AOP 开启@EnableAspectJAutoProxy 时注册的 AnnotationAwareAspectJProxyCreator实现的是同⼀个接⼝,所以说,声明式事务是 springAOP 思想的⼀种应⽤

ProxyTransactionManagementConfiguration

java 复制代码
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
		// 事务增强器
		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		// 向事务增强器中注⼊ 属性解析器 transactionAttributeSource
		advisor.setTransactionAttributeSource(transactionAttributeSource());
		// 向事务增强器中注⼊ 事务拦截器 transactionInterceptor
		advisor.setAdvice(transactionInterceptor());
		if (this.enableTx != null) {
			advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
		}
		return advisor;
	}

	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	// 属性解析器 transactionAttributeSource
	public TransactionAttributeSource transactionAttributeSource() {
		return new AnnotationTransactionAttributeSource();
	}

	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	// 事务拦截器 transactionInterceptor
	public TransactionInterceptor transactionInterceptor() {
		TransactionInterceptor interceptor = new TransactionInterceptor();
		interceptor.setTransactionAttributeSource(transactionAttributeSource());
		if (this.txManager != null) {
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}

}

ProxyTransactionManagementConfiguration是⼀个容器配置类,注册了⼀个组件transactionAdvisor,称为事务增强器,然后在这个事务增强器中⼜注⼊了两个属性:transactionAttributeSource ,即属性解析器transactionAttributeSource 和 事务拦截器transactionInterceptor

属性解析器 AnnotationTransactionAttributeSource 部分源码如下:

java 复制代码
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
		implements Serializable {

	private static final boolean jta12Present = ClassUtils.isPresent(
			"javax.transaction.Transactional", AnnotationTransactionAttributeSource.class.getClassLoader());

	private static final boolean ejb3Present = ClassUtils.isPresent(
			"javax.ejb.TransactionAttribute", AnnotationTransactionAttributeSource.class.getClassLoader());

	private final boolean publicMethodsOnly;
	// 注解解析器集合
	private final Set<TransactionAnnotationParser> annotationParsers;

属性解析器有⼀个成员变量是annotationParsers,是⼀个集合,可以添加多种注解解析器(TransactionAnnotationParser),我们关注 Spring 的注解解析器,部分源码如下


属性解析器的作⽤之⼀就是⽤来解析@Transaction注解

TransactionInterceptor 事务拦截器


上述组件如何关联起来的?

  • 事务拦截器实现了MethodInterceptor接⼝,追溯⼀下上⾯提到的InfrastructureAdvisorAutoProxyCreator后置处理器,它会在代理对象执⾏⽬标⽅法的时候获取其拦截器链,⽽拦截器链就是这个TransactionInterceptor,这就把这两个组件联系起来;
    构造⽅法传⼊PlatformTransactionManager(事务管理器)、TransactionAttributeSource(属性解析器),但是追溯⼀下上⾯贴的ProxyTransactionManagementConfiguration的源码,
    在注册事务拦截器的时候并没有调⽤这个带参构造⽅法,⽽是调⽤的⽆参构造⽅法,然后再调⽤set⽅法注⼊这两个属性,效果⼀样。

invokeWithinTransaction ⽅法源码如下:

java 复制代码
	//模板方法目标
	//1、获取事务属性
	//2、创建事务
	//3、调用目标方法
	//4、回滚 事务 or  提交事务
	@Nullable
	protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
											 final InvocationCallback invocation) throws Throwable {

		// 获取事务属性,如果事务属性为空,则没有事务
		TransactionAttributeSource tas = getTransactionAttributeSource();
		//继承TransactionDefinition,返回默认的传播、隔离级别
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
		// 获取DataSourceTransactionManager 用于管理 JDBC 的 Connection。
		final PlatformTransactionManager tm = determineTransactionManager(txAttr);
		// 切点标识-->com.tx.test.impl.UserServiceImpl.insert
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
		//txAttr(传播属性&隔离级别)
		if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
			// TODO: 创建(开启)事务(根据事务的传播行为属性去判断是否创建一个事务)
			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
			Object retVal = null;
			try {
				// TODO: 调用目标方法  org.springframework.aop.framework.ReflectiveMethodInvocation.proceed
				retVal = invocation.proceedWithInvocation();
			} catch (Throwable ex) {
				// TODO: 回滚事务  目标方法调用发生了异常(后置增强),
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			} finally {
				// 执行成功  清理信息
				cleanupTransactionInfo(txInfo);
			}
			//TODO: 提交事务
			commitTransactionAfterReturning(txInfo);
			return retVal;
		} else {
			final ThrowableHolder throwableHolder = new ThrowableHolder();

			// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
			try {
				Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
					TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
					try {
						return invocation.proceedWithInvocation();
					} catch (Throwable ex) {
						...
					} finally {
						cleanupTransactionInfo(txInfo);
					}
				});

				// Check result state: It might indicate a Throwable to rethrow.
				if (throwableHolder.throwable != null) {
					throw throwableHolder.throwable;
				}
				return result;
			} catch (ThrowableHolderException ex) {
				throw ex.getCause();
			} catch (TransactionSystemException ex2) {
				。。。
			}
		}
	}
相关推荐
qq_三哥啊1 小时前
【IDEA】设置Debug调试时调试器不进入特定类(Spring框架、Mybatis框架)
spring·intellij-idea·mybatis
别惹CC2 小时前
Spring AI 进阶之路01:三步将 AI 整合进 Spring Boot
人工智能·spring boot·spring
寒士obj2 小时前
Spring事物
java·spring
IT毕设实战小研10 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
甄超锋11 小时前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat
Java小白程序员14 小时前
Spring Framework:Java 开发的基石与 Spring 生态的起点
java·数据库·spring
甄超锋15 小时前
Java Maven更换国内源
java·开发语言·spring boot·spring·spring cloud·tomcat·maven
还是鼠鼠16 小时前
tlias智能学习辅助系统--Maven 高级-私服介绍与资源上传下载
java·spring boot·后端·spring·maven
还是大剑师兰特17 小时前
Spring面试题及详细答案 125道(1-15) -- 核心概念与基础1
spring·大剑师·spring面试题·spring教程
python_13620 小时前
web请求和响应
java·spring·github