@Transaction 原理


前言

本章研究的源码基于 springboot 2.7.3
因为 spring 的事务是基于 aop 实现的,所以需要了解一下 aop 的基本原理, 可以参考另外一篇文章 aop原理解析


一、事务的自动配置

1.1 自动配置类的注入

事务是 springboot 本身自带的功能, 因此自动配置类在 org.springframework.boot.autoconfigure.AutoConfiguration.imports 这个文件中, spring将自己的自动配置类都放到了这一个文件中
spring.factories 在更高的版本中将被彻底废弃

在这里插入图片描述

1.2 TransactionAutoConfiguration

它负责注入一些支持事务的类,核心类为 JdkDynamicAutoProxyConfigurationCglibAutoProxyConfiguration,这两个类上面都标注了 EnableTransactionManagement 注解,这个注解引入了别的一些配置类

@AutoConfiguration(after = { JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
		DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class })
@ConditionalOnClass(PlatformTransactionManager.class)
@EnableConfigurationProperties(TransactionProperties.class)
public class TransactionAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean
	public TransactionManagerCustomizers platformTransactionManagerCustomizers(
			ObjectProvider<PlatformTransactionManagerCustomizer<?>> customizers) {
		return new TransactionManagerCustomizers(customizers.orderedStream().collect(Collectors.toList()));
	}

	@Bean
	@ConditionalOnMissingBean
	@ConditionalOnSingleCandidate(ReactiveTransactionManager.class)
	public TransactionalOperator transactionalOperator(ReactiveTransactionManager transactionManager) {
		return TransactionalOperator.create(transactionManager);
	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnSingleCandidate(PlatformTransactionManager.class)
	public static class TransactionTemplateConfiguration {

		@Bean
		@ConditionalOnMissingBean(TransactionOperations.class)
		public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
			return new TransactionTemplate(transactionManager);
		}

	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnBean(TransactionManager.class)
	@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
	public static class EnableTransactionManagementConfiguration {

		@Configuration(proxyBeanMethods = false)
		@EnableTransactionManagement(proxyTargetClass = false)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")
		public static class JdkDynamicAutoProxyConfiguration {

		}

		/**
		 * 如果什么都没有配置的话会使用 Cglib 代理目标类
		 */
		@Configuration(proxyBeanMethods = false)
		@EnableTransactionManagement(proxyTargetClass = true)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
				matchIfMissing = true)
		public static class CglibAutoProxyConfiguration {

		}
	}
}

1.3 @EnableTransactionManagement

引入了另外一个核心的配置了 TransactionManagementConfigurationSelector

// 引入了 TransactionManagementConfigurationSelector
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

	boolean proxyTargetClass() default false;
	// 简单记一下这个 AdviceMode = AdviceMode.PROXY
	AdviceMode mode() default AdviceMode.PROXY;

	int order() default Ordered.LOWEST_PRECEDENCE;

}

1.3 TransactionManagementConfigurationSelector

这个类是一个 ImportSelector,会将 selectImports 方法返回的全路径类名引入 spring,当前类又引入了一个 ProxyTransactionManagementConfiguration(重要)AutoProxyRegistrar(不重要)

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
	
	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		// 这里是 PROXY, 因为这个是 EnableTransactionManagement 上配置的
		switch (adviceMode) {
			case PROXY:
				// 引入核心类 ProxyTransactionManagementConfiguration
				return new String[] {AutoProxyRegistrar.class.getName(),
						ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
				return new String[] {determineTransactionAspectClass()};
			default:
				return null;
		}
	}
	。。。
}

1.4 ProxyTransactionManagementConfiguration

这个类注入了 spring 事务实现的核心类 BeanFactoryTransactionAttributeSourceAdvisorTransactionInterceptor

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

	/**
	 * 注入了一个 Advisor, Advisor 就是 spring 用来创建 aop 代理的
	 * Advisor 有一个 advice 属性, Advice 一般都继承了 MethodInterceptor(这个就是CGLIB的方法拦截器)
	 * 因此事务方法的执行必定会经过 TransactionInterceptor
	 */
	@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.<Integer>getNumber("order"));
		}
		return advisor;
	}

	/**
	 * 引入了TransactionAttributeSource
	 * 这个类是用来创建代理对象的时候判断是否需要被 TransactionInterceptor 拦截的
	 */
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
		return new AnnotationTransactionAttributeSource();
	}

	/**
	 * 引入了拦截器 TransactionInterceptor
	 */
	@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;
	}

}

二、@Transaction 注解的扫描(事务代理对象的创建)

这里直接跳过 spring 的生命周期流程,直接看事务代理对象的创建过程
aop原理篇说过,spring 的代理都是通过一个核心类 AbstractAutoProxyCreator 的子类创建的,而这个类的注解实现类是 AnnotationAwareAspectJAutoProxyCreator(是一个 SmartInstantiationAwareBeanPostProcessor),代理对象的创建在该类的 postProcessAfterInitialization 方法中

2.1 代理对象创建核心方法 wrapIfNecessary

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	...
	// 获取能够拦截该 bean 的拦截器(Advisor)
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	if (specificInterceptors != DO_NOT_PROXY) {
		this.advisedBeans.put(cacheKey, Boolean.TRUE);
		// 创建代理对象
		Object proxy = createProxy(
				bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
		this.proxyTypes.put(cacheKey, proxy.getClass());
		return proxy;
	}

	this.advisedBeans.put(cacheKey, Boolean.FALSE);
	return bean;
}

2.2 过滤出符合条件的 Advisor(getAdvicesAndAdvisorsForBean)

@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
		Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

	List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
	if (advisors.isEmpty()) {
		return DO_NOT_PROXY;
	}
	return advisors.toArray();
}

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
	// 获取出所有的 Advisor
	List<Advisor> candidateAdvisors = findCandidateAdvisors();
	// 获取能够应用在该 bean 上的 Advisor
	List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
	extendAdvisors(eligibleAdvisors);
	if (!eligibleAdvisors.isEmpty()) {
		eligibleAdvisors = sortAdvisors(eligibleAdvisors);
	}
	return eligibleAdvisors;
}

2.3 findAdvisorsThatCanApply

protected List<Advisor> findAdvisorsThatCanApply(
	List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

	ProxyCreationContext.setCurrentProxiedBeanName(beanName);
	try {
		// 调用 AopUtils.findAdvisorsThatCanApply
		return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
	}
	finally {
		ProxyCreationContext.setCurrentProxiedBeanName(null);
	}
}

/**
 * 循环判断每个 Advisor 是否能够应用到 clazz 上
 */
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
	if (candidateAdvisors.isEmpty()) {
		return candidateAdvisors;
	}
	List<Advisor> eligibleAdvisors = new ArrayList<>();
	for (Advisor candidate : candidateAdvisors) {
		// 该方法的终极判断交给了 canApply
		if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
			eligibleAdvisors.add(candidate);
		}
	}
	boolean hasIntroductions = !eligibleAdvisors.isEmpty();
	for (Advisor candidate : candidateAdvisors) {
		if (candidate instanceof IntroductionAdvisor) {
			// already processed
			continue;
		}
		if (canApply(candidate, clazz, hasIntroductions)) {
			eligibleAdvisors.add(candidate);
		}
	}
	return eligibleAdvisors;
}

2.4 AopUtils#canApply

看代码前要再次提醒, 事务的自动配置了注入的 Advisor 是 BeanFactoryTransactionAttributeSourceAdvisor,这个 Advisor 是一个 PointcutAdvisor

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
	if (advisor instanceof IntroductionAdvisor) {
		return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
	}
	else if (advisor instanceof PointcutAdvisor) {
		PointcutAdvisor pca = (PointcutAdvisor) advisor;
		// 最终交给了 Pointcut 来判断,很合理,想想 Aop 不也是根据 pointcut 来判断的吗
		// 注意:pca 是 BeanFactoryTransactionAttributeSourceAdvisor
		return canApply(pca.getPointcut(), targetClass, hasIntroductions);
	}
	else {
		// It doesn't have a pointcut so we assume it applies.
		return true;
	}
}
/**
 * 对于事务来讲 Advisor 是 BeanFactoryTransactionAttributeSourceAdvisor
 * 那 pc 我们要去 BeanFactoryTransactionAttributeSourceAdvisor 这个类里面看一下
 * 它其实是 BeanFactoryTransactionAttributeSourceAdvisor 的一个内部类(TransactionAttributeSourcePointcut)
 */
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
	Assert.notNull(pc, "Pointcut must not be null");
	// classFilter 是 TransactionAttributeSourceClassFilter
	// 判断类上是否标注了 @Transaction 注解,其实这里基本上所有的都返回 true
	if (!pc.getClassFilter().matches(targetClass)) {
		return false;
	}
	// 方法匹配,对于事务来讲就是判断方法上是否标注了 @Transaction 注解
	MethodMatcher methodMatcher = pc.getMethodMatcher();
	if (methodMatcher == MethodMatcher.TRUE) {
		// No need to iterate the methods if we're matching any method anyway...
		return true;
	}
	
	IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
	if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
		introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
	}

	Set<Class<?>> classes = new LinkedHashSet<>();
	if (!Proxy.isProxyClass(targetClass)) {
		classes.add(ClassUtils.getUserClass(targetClass));
	}
	classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

	for (Class<?> clazz : classes) {
		Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
		for (Method method : methods) {
			// 判断方法上是否标注了 @Transaction 注解,如果标注了返回true
			// 返回 true 就表示这个 Advisor 将拦截当前方法
			if (introductionAwareMethodMatcher != null ?
					introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
					methodMatcher.matches(method, targetClass)) {
				return true;
			}
		}
	}

	return false;
}

2.5 TransactionAttributeSourcePointcut

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

	protected TransactionAttributeSourcePointcut() {
		// 设置过滤器 TransactionAttributeSourceClassFilter 是一个内部类,在下面
		setClassFilter(new TransactionAttributeSourceClassFilter());
	}


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

	/**
	 * Obtain the underlying TransactionAttributeSource (may be {@code null}).
	 * To be implemented by subclasses.
	 */
	@Nullable
	protected abstract TransactionAttributeSource getTransactionAttributeSource();


	/**
	 * {@link ClassFilter} that delegates to {@link TransactionAttributeSource#isCandidateClass}
	 * for filtering classes whose methods are not worth searching to begin with.
	 */
	private class TransactionAttributeSourceClassFilter implements ClassFilter {

		@Override
		public boolean matches(Class<?> clazz) {
			if (TransactionalProxy.class.isAssignableFrom(clazz) ||
					TransactionManager.class.isAssignableFrom(clazz) ||
					PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
				return false;
			}
			// 最终会调用 TransactionAttributeSource#isCandidateClass
			// 而在 ProxyTransactionManagementConfiguration 中已经注入了一个 TransactionAttributeSource
			// 为 AnnotationTransactionAttributeSource
			TransactionAttributeSource tas = getTransactionAttributeSource();
			return (tas == null || tas.isCandidateClass(clazz));
		}
	}
}

2.6 AnnotationTransactionAttributeSource

/**
 * 构造器
 */
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
	if (jta12Present || ejb3Present) {
		。。。
	}
	else {
		// 保存了一个 SpringTransactionAnnotationParser
		// SpringTransactionAnnotationParser 中就能看到 @Transaction 注解的扫描了
		this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
	}
}
/**
 * 判断是否符合条件
 */
@Override
public boolean isCandidateClass(Class<?> targetClass) {
	for (TransactionAnnotationParser parser : this.annotationParsers) {
		if (parser.isCandidateClass(targetClass)) {
			return true;
		}
	}
	return false;
}

2.7 SpringTransactionAnnotationParser

/**
 * SpringTransactionAnnotationParser#isCandidateClass
 * 判断类上是否有 @Transactional 注解
 */ 
@Override
public boolean isCandidateClass(Class<?> targetClass) {
	return AnnotationUtils.isCandidateClass(targetClass, Transactional.class);
}

三、事务处理的流程

核心类 TransactionInterceptor,是事务方法的拦截器

3.1 TransactionInterceptor#invoke

@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
	
	Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
	// 调用 invokeWithinTransaction() 并且传入了一个 callback
	return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
		@Override
		@Nullable
		public Object proceedWithInvocation() throws Throwable {
			// 调用目标方法
			return invocation.proceed();
		}
		@Override
		public Object getTarget() {
			return invocation.getThis();
		}
		@Override
		public Object[] getArguments() {
			return invocation.getArguments();
		}
	});
}

3.2 invokeWithinTransaction

@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
		final InvocationCallback invocation) throws Throwable {

	// 获取 @Transaction 注解上标注的属性
	TransactionAttributeSource tas = getTransactionAttributeSource();
	final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
	// 获取事务管理器
	final TransactionManager tm = determineTransactionManager(txAttr);
	// 这个 if 是适配 reactive,这里不管
	if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
		。。。
	}
	// 事务管理器必须是一个 PlatformTransactionManager,否则抛出异常
	PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
	// 目标方法的全路径名
	final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

	if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
		// 创建事务
		TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

		Object retVal;
		try {
			// 执行目标方法
			retVal = invocation.proceedWithInvocation();
		}
		catch (Throwable ex) {
			// 回滚事务
			completeTransactionAfterThrowing(txInfo, ex);
			throw ex;
		}
		finally {
			// 清理事务数据
			cleanupTransactionInfo(txInfo);
		}

		if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
			// Set rollback-only in case of Vavr failure matching our rollback rules...
			TransactionStatus status = txInfo.getTransactionStatus();
			if (status != null && txAttr != null) {
				retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
			}
		}
		// 事务正常执行, 提交事务
		commitTransactionAfterReturning(txInfo);
		return retVal;
	}

	else {
		。。。
	}
}

3.3 获取事务管理器 determineTransactionManager

@Nullable
protected TransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
	// 如果 @Transaction 指定了事务管理器则使用指定的事务管理器
	if (txAttr == null || this.beanFactory == null) {
		return 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 {
		TransactionManager defaultTransactionManager = getTransactionManager();
		if (defaultTransactionManager == null) {
			defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
			if (defaultTransactionManager == null) {
				// 从 Spring 容器中获取 TransactionManager
				// 默认获取到的是 JdbcTransactionManager 可以查看 4.1 章节
				defaultTransactionManager = this.beanFactory.getBean(TransactionManager.class);
				this.transactionManagerCache.putIfAbsent(
						DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
			}
		}
		return defaultTransactionManager;
	}
}

3.4 创建并开启事务 createTransactionIfNecessary

/**
 * 创建事务如果需要的话
 */
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
			@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
	// 将 txAttr 包一层
	if (txAttr != null && txAttr.getName() == null) {
		txAttr = new DelegatingTransactionAttribute(txAttr) {
			@Override
			public String getName() {
				return joinpointIdentification;
			}
		};
	}

	TransactionStatus status = null;
	if (txAttr != null) {
		if (tm != null) {
			// 从事务管理器中根据 @Transaction 上标注的属性获取事务
			status = tm.getTransaction(txAttr);
		}
		。。。
	}
	return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
/**
 * tm.getTransaction()
 */
@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
		throws TransactionException {

	// 如何 definition 为 null, 使用默认的
	TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
	// 尝试获取已经存在的 transaction(DataSourceTransactionObject)
	Object transaction = doGetTransaction();
	boolean debugEnabled = logger.isDebugEnabled();
	// 如果已经存在事务的话
	if (isExistingTransaction(transaction)) {
		// 事务的传播行为:当前已经在事务中了,如何处理当前事务
		return handleExistingTransaction(def, transaction, debugEnabled);
	}

	// 判断事务超时
	if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
		throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
	}

	// 如果事务的传播行为为 MANDATORY(必须存在事务), 并且当前没有已经存在的事务, 抛出异常
	if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
		throw new IllegalTransactionStateException(
				"No existing transaction found for transaction marked with propagation 'mandatory'");
	}
	/**
	 * NESTED:如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。
	 * 如果当前事务不存在,那么其行为与Required一样
	 */
	else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
			def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
			def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
		// 将当前事务的所有信息保存在 SuspendedResourcesHolder 中,也就是挂起
		SuspendedResourcesHolder suspendedResources = suspend(null);
		
		try {
		   	// 开启事务
			return startTransaction(def, transaction, debugEnabled, suspendedResources);
		}
		catch (RuntimeException | Error ex) {
			resume(null, suspendedResources);
			throw ex;
		}
	}
	else {
		。。。
	}
}
/**
 * 开启事务
 * 会创建数据库连接
 * startTransaction
 */
private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,
		boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {

	boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
	DefaultTransactionStatus status = newTransactionStatus(
			definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
	// 开启事务
	doBegin(transaction, definition);
	prepareSynchronization(status, definition);
	return status;
}
/**
 * doBegin
 */
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
	Connection con = null;

	try {
		if (!txObject.hasConnectionHolder() ||
				txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
			// 从数据源中获取数据库连接
			Connection newCon = obtainDataSource().getConnection();
			if (logger.isDebugEnabled()) {
				logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
			}
			txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
		}

		txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
		con = txObject.getConnectionHolder().getConnection();

		Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
		txObject.setPreviousIsolationLevel(previousIsolationLevel);
		txObject.setReadOnly(definition.isReadOnly());

		// 设置不自动提交
		if (con.getAutoCommit()) {
			txObject.setMustRestoreAutoCommit(true);
			if (logger.isDebugEnabled()) {
				logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
			}
			con.setAutoCommit(false);
		}

		prepareTransactionalConnection(con, definition);
		txObject.getConnectionHolder().setTransactionActive(true);

		int timeout = determineTimeout(definition);
		if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
			txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
		}

		// 绑定连接
		if (txObject.isNewConnectionHolder()) {
			TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
		}
	}

	catch (Throwable ex) {
		if (txObject.isNewConnectionHolder()) {
			DataSourceUtils.releaseConnection(con, obtainDataSource());
			txObject.setConnectionHolder(null, false);
		}
		throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
	}
}

3.4 回滚操作

protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
	if (txInfo != null && txInfo.getTransactionStatus() != null) {
		if (logger.isTraceEnabled()) {
			logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
					"] after exception: " + ex);
		}
		/**
		 * txInfo.transactionAttribute.rollbackOn(ex)
		 * 这个方法判断遇到当前异常是否需要回滚
		 */
		if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
			try {
				txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
			}
			。。。
		}
		else {
			// 如果上面没有回滚, 则提交当前事务
			try {
				txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
			}
			。。。
		}
	}
}
/**
 * RuleBasedTransactionAttribute#rollbackOn
 */
@Override
public boolean rollbackOn(Throwable ex) {
	RollbackRuleAttribute winner = null;
	int deepest = Integer.MAX_VALUE;

	if (this.rollbackRules != null) {
		// rollbackRules 就是我们在 @Transaction 配置的回滚的异常类
		for (RollbackRuleAttribute rule : this.rollbackRules) {
			int depth = rule.getDepth(ex);
			// 判断是否匹配到了我们标注的异常
			if (depth >= 0 && depth < deepest) {
				deepest = depth;
				winner = rule;
			}
		}
	}

	//如果没有匹配到我们配置的,或者我们没有配置,使用父类自带的回滚异常
	// 父类:return (ex instanceof RuntimeException || ex instanceof Error);
	// 有此可见,默认 spring 只会回滚 RuntimeException 和 Error
	if (winner == null) {
		return super.rollbackOn(ex);
	}

	return !(winner instanceof NoRollbackRuleAttribute);
}

3.5 提交事务

protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
		if (logger.isTraceEnabled()) {
			logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
		}
		// 提交事务
		txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
	}
}
/**
 * AbstractPlatformTransactionManager#commit
 */
@Override
public final void commit(TransactionStatus status) throws TransactionException {
	if (status.isCompleted()) {
		throw new IllegalTransactionStateException(
				"Transaction is already completed - do not call commit or rollback more than once per transaction");
	}
	// 由此可见我们其实可以在 spring 就算没有异常抛出的情况下依然回滚事务
	DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
	if (defStatus.isLocalRollbackOnly()) {
		if (defStatus.isDebug()) {
			logger.debug("Transactional code has requested rollback");
		}
		processRollback(defStatus, false);
		return;
	}

	if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
		if (defStatus.isDebug()) {
			logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
		}
		processRollback(defStatus, true);
		return;
	}
	// 提交事务
	processCommit(defStatus);
}
/**
 * AbstractPlatformTransactionManager#processCommit
 * 这个方法主要是处理提交前后的一些钩子方法
 * cleanupAfterCompletion 这个方法比较重要,这个方法会恢复之前被挂起的事务数据
 */
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
	try {
		boolean beforeCompletionInvoked = false;

		try {
			boolean unexpectedRollback = false;
			prepareForCommit(status);
			triggerBeforeCommit(status);
			triggerBeforeCompletion(status);
			beforeCompletionInvoked = true;
			// savepoint
			if (status.hasSavepoint()) {
				if (status.isDebug()) {
					logger.debug("Releasing transaction savepoint");
				}
				unexpectedRollback = status.isGlobalRollbackOnly();
				status.releaseHeldSavepoint();
			}
			// 如果是一个新的事务,直接提交
			else if (status.isNewTransaction()) {
				if (status.isDebug()) {
					logger.debug("Initiating transaction commit");
				}
				unexpectedRollback = status.isGlobalRollbackOnly();
				doCommit(status);
			}
			else if (isFailEarlyOnGlobalRollbackOnly()) {
				unexpectedRollback = status.isGlobalRollbackOnly();
			}

			// Throw UnexpectedRollbackException if we have a global rollback-only
			// marker but still didn't get a corresponding exception from commit.
			if (unexpectedRollback) {
				throw new UnexpectedRollbackException(
						"Transaction silently rolled back because it has been marked as rollback-only");
			}
		}
		。。。
		try {
			triggerAfterCommit(status);
		}
		finally {
			triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
		}

	}
	finally {
		// 恢复事务数据 (TransactionSynchronizationManager) 里有几个 ThreadLocal
		cleanupAfterCompletion(status);
	}
}

3.6 事务的传播行为

3.6.0 前置知识

getTransaction 与 handleExistingTransaction

getTransaction 后半部分代码是当前没有事务的处理逻辑
handleExistingTransaction 是处理当前存在事务的逻辑
因此事务传播行为由这两部分组成


事务挂起
/**
 * AbstractPlatformTransactionManager#suspend
 * 返回了一个 SuspendedResourcesHolder
 * SuspendedResourcesHolder 中保存了当前事务运行的一些数据,比如说数据库连接, 可以看 4.2 章节
 * 这个会被保存在 DefaultTransactionStatus 中,后续事务提交之后会通过这个对象获取出来,然后在恢复
 */
@Nullable
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
	if (TransactionSynchronizationManager.isSynchronizationActive()) {
		List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
		try {
			Object suspendedResources = null;
			if (transaction != null) {
				suspendedResources = doSuspend(transaction);
			}
			String name = TransactionSynchronizationManager.getCurrentTransactionName();
			TransactionSynchronizationManager.setCurrentTransactionName(null);
			boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
			TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
			Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
			TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
			boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
			TransactionSynchronizationManager.setActualTransactionActive(false);
			return new SuspendedResourcesHolder(
					suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
		}
		catch (RuntimeException | Error ex) {
			// doSuspend failed - original transaction is still active...
			doResumeSynchronization(suspendedSynchronizations);
			throw ex;
		}
	}
	else if (transaction != null) {
		// Transaction active but no synchronization active.
		Object suspendedResources = doSuspend(transaction);
		return new SuspendedResourcesHolder(suspendedResources);
	}
	else {
		// Neither transaction nor synchronization active.
		return null;
	}
}
事务恢复

事务恢复操作一般在新的事务提交了之后

/**
 * AbstractPlatformTransactionManager#resume
 */
protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)
			throws TransactionException {

	if (resourcesHolder != null) {
		Object suspendedResources = resourcesHolder.suspendedResources;
		if (suspendedResources != null) {
			doResume(transaction, suspendedResources);
		}
		List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;
		if (suspendedSynchronizations != null) {
			TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);
			TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);
			TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);
			TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);
			doResumeSynchronization(suspendedSynchronizations);
		}
	}
}

3.6.1 Propagation.REQUIRED

有事务就加入事务,没有事务就创建一个事务,默认值

/**
 * AbstractPlatformTransactionManager#getTransaction
 * 这个方法后面是处理当前没有事务的逻辑
 */
else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
		def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
		def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
	// 挂起了 null
	SuspendedResourcesHolder suspendedResources = suspend(null);
	if (debugEnabled) {
		logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
	}
	try {
		// 新创建一个事务
		return startTransaction(def, transaction, debugEnabled, suspendedResources);
	}
	catch (RuntimeException | Error ex) {
		resume(null, suspendedResources);
		throw ex;
	}
}

3.6.2 Propagation.REQUIRES_NEW

每次都新建一个事务

/**
 * AbstractPlatformTransactionManager#handleExistingTransaction
 */
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
	if (debugEnabled) {
		logger.debug("Suspending current transaction, creating new transaction with name [" +
				definition.getName() + "]");
	}
	// 将原来的事务挂起
	SuspendedResourcesHolder suspendedResources = suspend(transaction);
	try {
		// startTransaction 会创建一个新的事务(回创建新的数据库连接)
		return startTransaction(definition, transaction, debugEnabled, suspendedResources);
	}
	catch (RuntimeException | Error beginEx) {
		resumeAfterBeginException(transaction, suspendedResources, beginEx);
		throw beginEx;
	}
}

3.6.3 Propagation.SUPPORTS

当前有事务就加入事务, 没有事务就当作非事务运行
springboot 源码中并没有对 SUPPORTS 的直接判断,而是走了 else 逻辑

3.6.4 Propagation.MANDATORY

如果不存在事务就抛出异常

/**
 * AbstractPlatformTransactionManager#getTransaction
 */
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
	throw new IllegalTransactionStateException(
			"No existing transaction found for transaction marked with propagation 'mandatory'");
}

3.6.5 Propagation.NOT_SUPPORTED

以非事务运行, 如果存在事务,将当前事务挂起

/**
 * AbstractPlatformTransactionManager#handleExistingTransaction
 */
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
	if (debugEnabled) {
		logger.debug("Suspending current transaction");
	}
	// 挂起当前事务
	Object suspendedResources = suspend(transaction);
	// 并没有创建新的事务
	boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
	return prepareTransactionStatus(
			definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}

3.6.6 Propagation.NEVER

如果存在事务就抛出异常

/**
 * AbstractPlatformTransactionManager#handleExistingTransaction
 */
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
	throw new IllegalTransactionStateException(
			"Existing transaction found for transaction marked with propagation 'never'");
}

3.6.7 Propagation.NESTED

如果存在外部事务则创建事务来作为当前事务的嵌套事务,如果没有外部事务,则等价于Propagation.REQUIRED

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
	// 判断是否支持嵌套事务
	if (!isNestedTransactionAllowed()) {
		throw new NestedTransactionNotSupportedException(
				"Transaction manager does not allow nested transactions by default - " +
				"specify 'nestedTransactionAllowed' property with value 'true'");
	}
	if (debugEnabled) {
		logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
	}
	// 使用保存点
	if (useSavepointForNestedTransaction()) {
		// Create savepoint within existing Spring-managed transaction,
		// through the SavepointManager API implemented by TransactionStatus.
		// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
		DefaultTransactionStatus status =
				prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
		status.createAndHoldSavepoint();
		return status;
	}
	else {
		// 创建一个新的事务,注意:并没有挂起原来的事务,因此是嵌套事务
		return startTransaction(definition, transaction, debugEnabled, null);
	}
}

四、其他源码

4.1 事务管理器的注入

4.1.1 事务管理器自动配置类

在这里插入图片描述

4.1.2 DataSourceTransactionManagerAutoConfiguration

/**
 * 事务管理器的自动配置类
 */
@AutoConfiguration
@ConditionalOnClass({ JdbcTemplate.class, TransactionManager.class })
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceTransactionManagerAutoConfiguration {

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnSingleCandidate(DataSource.class)
	static class JdbcTransactionManagerConfiguration {

		/**
		 * 注入事务管理器
		 */
		@Bean
		@ConditionalOnMissingBean(TransactionManager.class)
		DataSourceTransactionManager transactionManager(Environment environment, DataSource dataSource,
				ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
			// 创建事务管理器
			DataSourceTransactionManager transactionManager = createTransactionManager(environment, dataSource);
			// 可以对事务管理器进行自定义处理
			transactionManagerCustomizers.ifAvailable((customizers) -> customizers.customize(transactionManager));
			return transactionManager;
		}

		/**
		 * 创建事务管理器
		 */
		private DataSourceTransactionManager createTransactionManager(Environment environment, DataSource dataSource) {
			/** 
			 * 从 environment 中获取这个属性
			 * 如果是 true 返回 JdbcTransactionManager, false 返回 DataSourceTransactionManager
			 * 默认是 true, 也就是默认的 TransactionManager 是 JdbcTransactionManager
			 */
			return environment.getProperty("spring.dao.exceptiontranslation.enabled", Boolean.class, Boolean.TRUE) ? new JdbcTransactionManager(dataSource) : new DataSourceTransactionManager(dataSource);
		}

	}

}

4.2 TransactionSynchronizationManager

public abstract class TransactionSynchronizationManager {
	// resources 中存放的是 ConnectionHolder,可以简单理解为数据库连接对象
	private static final ThreadLocal<Map<Object, Object>> resources =
			new NamedThreadLocal<>("Transactional resources");

	private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
			new NamedThreadLocal<>("Transaction synchronizations");
	// 当前事务名称: 一般是方法的全路径名
	private static final ThreadLocal<String> currentTransactionName =
			new NamedThreadLocal<>("Current transaction name");
	// 当前事务是否只读
	private static final ThreadLocal<Boolean> currentTransactionReadOnly =
			new NamedThreadLocal<>("Current transaction read-only status");
	// 当前事务隔离级别
	private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
			new NamedThreadLocal<>("Current transaction isolation level");
	// 
	private static final ThreadLocal<Boolean> actualTransactionActive =
			new NamedThreadLocal<>("Actual transaction active");
}

五、事务使用的注意事项

5.1 事务失效场景

spring 事务实现的本质是基于代理,抛出异常之后代理对象捕获到异常才会回滚, 因此事务失效总而言之可分为

  1. 没有创建出正确的代理对象
  2. 抛出的异常未被代理对象捕获到,默认 spring 只会回滚 RuntimeExceptionError,除了这些异常别的异常需要手动指定

总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值