10 事务

felix.shao2025-03-07

10 事务

前述

 Spring 声明式事务让我们从复杂的事务处理中得到解脱,使开发不再需要处理获得连接、关闭连接、事务提交和回滚等操作,再也不需要在与事务相关的方法中处理大量的 try...catch...finally 代码。

10.1 JDBC 方式下的事务使用示例

JDBC 方式下的事务使用示例

 使用步骤如下。

  1. 创建数据库表结构。
  2. 创建对应数据表的 PO。
  3. 创建表与实体间的映射
  4. 创建数据操作接口。
  5. 创建数据接口操作实现类。
  6. 创建 Spring 配置文件。
  7. 测试。  使用示例见代码 com.stu.spring.context.chapter10.tran.TranTest,因为抛出了 RuntimeException,所以数据并不会保存到数据库中。
     默认情况下 Spring 中的事务处理只对 RuntimeException 方法进行回滚。

10.2 事务自定义标签

AnnotationDrivenBeanDefinitionParser

 配置为 <tx:annotation-driven />,全局搜索找到下面代码入口。

public class TxNamespaceHandler extends NamespaceHandlerSupport {
	@Override
	public void init() {
		registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
		registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
		registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
	}
}

 根据自定义标签的使用规则及上面的代码,会找到 AnnotationDrivenBeanDefinitionParser 的 parse 方法进行解析。

package org.springframework.transaction.config;

// 注意 package,有重名类
class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
    public BeanDefinition parse(Element element, ParserContext parserContext) {
		registerTransactionalEventListenerFactory(parserContext);
		String mode = element.getAttribute("mode");
		if ("aspectj".equals(mode)) {
			// mode="aspectj"
			// <tx:annotation-driven transaction-manager="transactionManager" mode="aspectj" /> 时生效
			registerTransactionAspect(element, parserContext);
			if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) {
				registerJtaTransactionAspect(element, parserContext);
			}
		}
		else {
			// mode="proxy"
			AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
		}
		return null;
	}
}

 在解析中存在对于 mode 属性的判断,根据代码,如果我们需要使用 AspectJ 的方式进行事务切入(Spring 中的事务是以 AOP 为基础的),那么可以使用这样的配置。
<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>

10.2.1 注册 InfrastructureAdvisorAutoProxyCreator

configureAutoProxyCreator()

 以默认配置为例子进行分析。

class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
    private static class AopAutoProxyConfigurer {

		public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
			// 跟踪代码,发现是注册了 InfrastructureAdvisorAutoProxyCreator
			AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

			String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
			if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
				Object eleSource = parserContext.extractSource(element);

				/**
				 * 注册了代理类及 3 个 bean,这 3 个 bean 支撑了整个的事务功能。
				 */
				// 1 创建 TransactionAttributeSource 的 bean.
				RootBeanDefinition sourceDef = new RootBeanDefinition(
						"org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
				sourceDef.setSource(eleSource);
				sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
				// 注册 bean,并使用 Spring 中的定于规则生成 beanname
				String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

				// 2 创建 TransactionInterceptor 的 bean.
				RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
				interceptorDef.setSource(eleSource);
				interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
				registerTransactionManager(element, interceptorDef);
				interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
				// 注册 bean,并使用 Spring 中的定义规则生成 beanname
				String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

				// 3 创建 TransactionAttributeSourceAdvisor 的 bean
				RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
				advisorDef.setSource(eleSource);
				advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

				// 将 sourceName 的 bean 注入 advisorDef 的 transactionAttributeSource 属性中
				advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
				// 将 interceptorName 的 bean 注入 advisorDef 的 adviceBeanName 属性中
				advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
				// 如果配置了 order 属性,则加入到 bean 中
				if (element.hasAttribute("order")) {
					advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
				}
				parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);

				// 创建 CompositeComponentDefinition
				CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
				compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
				compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
				compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
				parserContext.registerComponent(compositeDef);
			}
		}
	}
}

 其中注册了代理类及 3 个 bean,这 3 个 bean 支撑了整个的事务功能,其中的两个 bean 被注册到了一个名为 advisorDef 的 bean 中,他们的关系如下

uml diagram

 一个个函数跟踪来理解吧。

 registerAutoProxyCreatorIfNecessary()
public abstract class AopNamespaceUtils {
    public static void registerAutoProxyCreatorIfNecessary(
			ParserContext parserContext, Element sourceElement) {

		BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(
				parserContext.getRegistry(), parserContext.extractSource(sourceElement));
		useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
		registerComponentIfNecessary(beanDefinition, parserContext);
	}
}

public abstract class AopConfigUtils {
    public static BeanDefinition registerAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {

		return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
	}
}
 InfrastructureAdvisorAutoProxyCreator 类层次结构如下
InfrastructureAdvisorAutoProxyCreator
    AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
        AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
            ProxyProcessorSupport (org.springframework.aop.framework)
                ProxyConfig (org.springframework.aop.framework)
                    Object (java.lang)
                    Serializable (java.io)
                Ordered (org.springframework.core)
                BeanClassLoaderAware (org.springframework.beans.factory)
                    Aware (org.springframework.beans.factory)
                AopInfrastructureBean (org.springframework.aop.framework)
            SmartInstantiationAwareBeanPostProcessor (org.springframework.beans.factory.config)
                InstantiationAwareBeanPostProcessor (org.springframework.beans.factory.config)
                    BeanPostProcessor (org.springframework.beans.factory.config)
            BeanFactoryAware (org.springframework.beans.factory)
                Aware (org.springframework.beans.factory)

 因此找到 BeanPostProcessor 接口的 postProcessAfterInitialization 方法,其实现类是在父类 AbstractAutoProxyCreator 中。

 postProcessAfterInitialization()

 以之前示例为例,当实例化 MyBookService 的 bean 时便会调用此方法:

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			// 根据给定的 bean 的 class 和 name 构建出一个 key,格式:beanClassName_beanName
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			// 是否是由于避免循环依赖二创建的 bean 代理
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				// 如果它适合被代理,则需要封装指定 bean
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// 如果已经处理过
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		// 无须增强
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		// 给定的 bean 类是否代表一个基础设施类,基础设施类不应代理,或者配置了指定 bean 不需要自动代理
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// 核心业务逻辑,如果存在增强方法则创建代理,AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
		// Create proxy if we have advice.
		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;
	}
}

 wrapIfNecessary 函数功能实现起来很复杂,但是逻辑上还是毕竟容易理解的,其主要工作如下。

  • 找出指定 bean 对应的增强器。
  • 根据找出的增强器创建代理。

10.2.2 获取对应 class/method 的增强器

 接 wrapIfNecessary 里面的代码进行分析。

 getAdvicesAndAdvisorsForBean()

 获取指定 bean 对应的增强器,其中包含两个关键字:增强器与对应,即在该方法中,不但要找出增强器,还要判断增强器是否满足要求。

public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
    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) {
		// 获取所有的增强
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		// 寻找所有增强中适用于 bean 的增强并应用,即加了 @Transaction 注解的 advisor 切面,beanClass 为需要代理的具体 Service 如 UserService
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}
}
  1. 寻找候选增强器
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
    protected List<Advisor> findCandidateAdvisors() {
		Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
		return this.advisorRetrievalHelper.findAdvisorBeans();
	}
}

public class BeanFactoryAdvisorRetrievalHelper {
    public List<Advisor> findAdvisorBeans() {
		// Determine list of advisor bean names, if not cached already.
		String[] advisorNames = this.cachedAdvisorBeanNames;
		if (advisorNames == null) {
			// 通过 BeanFactoryUtils 获取所有对应 Advisor.class 的类,
			// 获取办法是使用 ListableBeanFactory 中提供的方法 getBeanNamesForType
			// 我们知道容器中的 beanName 时,使用 getBean(String name, Class<T> requiredType) 获取增强器就很容易了
			advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
					this.beanFactory, Advisor.class, true, false);
			this.cachedAdvisorBeanNames = advisorNames;
		}
		if (advisorNames.length == 0) {
			return new ArrayList<>();
		}

		List<Advisor> advisors = new ArrayList<>();
		for (String name : advisorNames) {
			if (isEligibleBean(name)) {
				if (this.beanFactory.isCurrentlyInCreation(name)) {
					if (logger.isTraceEnabled()) {
						logger.trace("Skipping currently created advisor '" + name + "'");
					}
				}
				else {
					try {
						// Mark
						advisors.add(this.beanFactory.getBean(name, Advisor.class));
					}
					catch (BeanCreationException ex) {
						Throwable rootCause = ex.getMostSpecificCause();
						if (rootCause instanceof BeanCurrentlyInCreationException) {
							BeanCreationException bce = (BeanCreationException) rootCause;
							String bceBeanName = bce.getBeanName();
							if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
								if (logger.isTraceEnabled()) {
									logger.trace("Skipping advisor '" + name +
											"' with dependency on currently created bean: " + ex.getMessage());
								}
								// Ignore: indicates a reference back to the bean we're trying to advise.
								// We want to find advisors other than the currently created bean itself.
								continue;
							}
						}
						throw ex;
					}
				}
			}
		}
		return advisors;
	}
}

 我们回头再看 BeanFactoryTransactionAttributeSourceAdvisor,其也实现了 Advisor 接口,那么在获取所有增强器时也会将此 bean 提取出来,并随着其他增强器一起在后续的步骤中被织入代理。

  2. 候选增强器中寻找到匹配项

 当找出对应的增强器后,下面就是看这些增强器是否与对应的 class 及其内部的方法是否匹配了。

public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
    protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
		try {
			// 过滤已经得到的 advisors
			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
		}
		finally {
			ProxyCreationContext.setCurrentProxiedBeanName(null);
		}
	}
}

public abstract class AopUtils {
    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;
			}
			// 对于普通 bean 的处理
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}

    public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
      // advisor 即为 BeanFactoryTransactionAttributeSourceAdvisor
      if (advisor instanceof IntroductionAdvisor) {
        return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
      }
      else if (advisor instanceof PointcutAdvisor) {
        PointcutAdvisor pca = (PointcutAdvisor) advisor;
        // canApply 实现
        return canApply(pca.getPointcut(), targetClass, hasIntroductions);
      }
      else {
        // It doesn't have a pointcut so we assume it applies.
        return true;
      }
    }
}

 当前我们看的是 MyBookService 是否适用于此增强方法,那么当前的 advisor 就是之前查找出来的类型为 BeanFactoryTransactionAttributeSourceAdvisor 的 bean 实例。其又间接实现了 PointcutAdvisor。在 canApply 函数中的第二个 if 就会通过判断,会将 BeanFactoryTransactionAttributeSourceAdvisor 中的 getPointcut() 方法返回值作为参数继续调用 canApply 方法,而 getPointcut() 方法返回的是 TransactionAttributeSourcePointcut 类型的实例(解析自定义标签时传入的,对应的代码如下)。

class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
    private static class AopAutoProxyConfigurer {
        public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
            // ...
            // 3 创建 TransactionAttributeSourceAdvisor 的 bean
            RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
        }
    }
}

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
    private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
		@Override
		@Nullable
		protected TransactionAttributeSource getTransactionAttributeSource() {
			return transactionAttributeSource;
		}
	};
}

 继续跟踪 canApply,找到事务标签的提取过程代码。

public abstract class AopUtils {
    public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
		/**
		 * 首先获取对应类的所有接口并联通类本身一起遍历,遍历过程中又对类中的方法再次遍历,一旦匹配成功便认为这个类适用于当前增强器。
		 * 另外需注意,类接口上的配置可以延续到类中的每个函数,需要关注下 matcher 方法。
		 */
		Assert.notNull(pc, "Pointcut must not be null");
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}

		// 事务源码分析:
		// 此时的 pc 表示 TransactionAttributeSourcePointcut,pc.getMethodMatcher() 返回的正是自身 (this)
		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) {
				// methodMatcher.matches 会使用 TransactionAttributeSourcePointcut.matches 方法
				if (introductionAwareMethodMatcher != null ?
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
						methodMatcher.matches(method, targetClass)) {
					return true;
				}
			}
		}

		return false;
	}
}

 类本身上配置的事务属性也需要检测,继续看 matcher 方法。

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
    public boolean matches(Method method, Class<?> targetClass) {
		TransactionAttributeSource tas = getTransactionAttributeSource();
		// 事务时,此时的注解是 AnnotationTransactionAttributeSource 类型
        // 继续跟踪 TransactionAttributeSource.getTransactionAttribute 方法
		return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
	}
}

public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource {
    public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
		if (method.getDeclaringClass() == Object.class) {
			return null;
		}

		// First, see if we have a cached value.
		Object cacheKey = getCacheKey(method, targetClass);
		TransactionAttribute cached = this.attributeCache.get(cacheKey);
		if (cached != null) {
			// Value will either be canonical value indicating there is no transaction attribute,
			// or an actual transaction attribute.
			if (cached == NULL_TRANSACTION_ATTRIBUTE) {
				return null;
			}
			else {
				return cached;
			}
		}
		else {
			// 事务标签的提取过程
			// We need to work it out.
			TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
			// Put it in the cache.
			if (txAttr == null) {
				this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
			}
			else {
				String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
				if (txAttr instanceof DefaultTransactionAttribute) {
					((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
				}
				if (logger.isTraceEnabled()) {
					logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
				}
				this.attributeCache.put(cacheKey, txAttr);
			}
			return txAttr;
		}
	}
}

 事务标签的提取过程委托给了 computeTransactionAttribute 方法。

  3. 提取事务标签
public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource {
    protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
		// Don't allow no-public methods as required.
		if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
			return null;
		}

		// method 代表接口中的方法,specificMethod 代表实现类中的方法
		Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

		// 查看方法中是否存在事务声明
		TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
		if (txAttr != null) {
			return txAttr;
		}

		// 查看方法中是否存在事务声明
		txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
		if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
			return txAttr;
		}

		// 如果存在接口,则到接口中去寻找
		if (specificMethod != method) {
			// 查看方法所在类中是否存在事务声明
			// 没有真正的去做搜寻事务属性的逻辑,而是搭建了个执行框架,将搜寻事务属性的任务委托给了 findTransactionAttribute 方法
			txAttr = findTransactionAttribute(method);
			if (txAttr != null) {
				return txAttr;
			}
			// 到接口中的类中去寻找。
			txAttr = findTransactionAttribute(method.getDeclaringClass());
			if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
				return txAttr;
			}
		}

		return null;
	}
}

public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
		implements Serializable {
    protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
		return determineTransactionAttribute(clazz);
	}

    protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
		// this.annotationParsers 是在当前类初始化的时候初始化的,其中的值被加入了 SpringTransactionAnnotationParser
		// 也即是当进行属性获取的时候其实是使用 SpringTransactionAnnotationParser 类的 parseTransactionAnnotation 方法进行解析的。
		for (TransactionAnnotationParser parser : this.annotationParsers) {
			// 获取注解标签的代码
			TransactionAttribute attr = parser.parseTransactionAnnotation(element);
			if (attr != null) {
				return attr;
			}
		}
		return null;
	}
}

public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {
    public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
		AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
				element, Transactional.class, false, false);
		if (attributes != null) {
			return parseTransactionAnnotation(attributes);
		}
		else {
			return null;
		}
	}

    protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
		RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();

		// 解析 propagation
		Propagation propagation = attributes.getEnum("propagation");
		rbta.setPropagationBehavior(propagation.value());
		// 解析 isolation
		Isolation isolation = attributes.getEnum("isolation");
		rbta.setIsolationLevel(isolation.value());
		// 解析 timeout
		rbta.setTimeout(attributes.getNumber("timeout").intValue());
		// 解析 readOnly
		rbta.setReadOnly(attributes.getBoolean("readOnly"));
		// 解析 value
		rbta.setQualifier(attributes.getString("value"));

		List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
		// 解析 rollbackFor
		for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
			rollbackRules.add(new RollbackRuleAttribute(rbRule));
		}
		// 解析 rollbackForClassName
		for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
			rollbackRules.add(new RollbackRuleAttribute(rbRule));
		}
		// 解析 noRollbackFor
		for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
			rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
		}
		// 解析 noRollbackForClassName
		for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
			rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
		}
		rbta.setRollbackRules(rollbackRules);

		return rbta;
	}
}

 computeTransactionAttribute 的工作是,如果方法中存在事务属性,则使用方法上的属性,否则使用方法所在的类上的属性,如果方法所在类的属性上还是没有搜寻到对应的事务属性,那么再搜寻接口中的方法,再没有的话,最后尝试搜寻接口的类上面的声明。
 现在,我们以 MyBookServiceImpl 为例,已经在它的接口 MyBookService 中找到了事务属性,所以,它是与事务增强器匹配的,也就是它会被事务功能修饰。
 至此,事务功能的初始化工作便结束了,当判断某个 bean 适用于事务增强时,也就是适用于增强器 BeanFactoryTransationAttributeSourceAdvisor。它作为 Advisor 的实现类,当代理被调用时会调用这个类的增强方法,也就是此 bean 的 Advise,又因为在解析事务定义标签时我们把 TransactionInterceptor 类型的 bean 注入到了 BeanFactoryTransationAttributeSourceAdvisor 中,所以,在调用事务增强器增强的代理类时会首先执行 TransactionInterceptor 增强,同时,也就是在 TransactionInterceptor 类中的 invoke` 方法中完成了整个事务的逻辑。

10.3 事务增强器

TransactionInterceptor

 TransactionInterceptor 支撑着整个事务功能的架构,逻辑还是相对复杂的。我们一步步开始分析。
 TransactionInterceptor 类继承自 MethodInterceptor,所以调用该类是从其 invoke 方法开始的。

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
	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);
	}
}

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
	protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {

		// If the transaction attribute is null, the method is non-transactional.
		TransactionAttributeSource tas = getTransactionAttributeSource();
		// 1.1 获取事务的属性。
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);

		final TransactionManager tm = determineTransactionManager(txAttr);

		if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
			ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
				if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) {
					throw new TransactionUsageException(
							"Unsupported annotated transaction on suspending function detected: " + method +
							". Use TransactionalOperator.transactional extensions instead.");
				}
				ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
				if (adapter == null) {
					throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
							method.getReturnType());
				}
				return new ReactiveTransactionSupport(adapter);
			});
			return txSupport.invokeWithinTransaction(
					method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
		}

		// 1.2 加载配置中的 TransactionManager。
		// 获取 beanFactory 中的 transactionManager
		PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
		// 获取方法唯一表示(类.方法,如 service.MyBookServiceImpl.save)
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

		// 1.3 不同的事务处理方式使用不同的逻辑。
		// 编程式事务是没有事务属性的。
		// CallbackPreferringPlatformTransactionManager 实现 PlatformTransactionManager 接口,爆露出一个方法用于执行事务处理中的回调,因此可以用作事务处理方式的判断。
		if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
			// 声明式事务处理
			// 创建 TransactionInfo
			// 1.4 在目标方法执行前获取事务并收集事务信息。
			TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

			Object retVal;
			try {
				// 1.5 执行被增强方法。
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				// 1.6 一旦出现异常,尝试异常处理。
				// 默认只对 RuntimeException 回滚
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
				// 1.7 提交事务前的事务信息清除。
				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);
				}
			}

			// 1.8 提交事务。
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}

		else {
			// 编程式事务处理
			Object result;
			final ThrowableHolder throwableHolder = new ThrowableHolder();

			// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
			try {
				result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
					TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
					try {
						Object retVal = invocation.proceedWithInvocation();
						if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
							// Set rollback-only in case of Vavr failure matching our rollback rules...
							retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
						}
						return retVal;
					}
					catch (Throwable ex) {
						if (txAttr.rollbackOn(ex)) {
							// A RuntimeException: will lead to a rollback.
							if (ex instanceof RuntimeException) {
								throw (RuntimeException) ex;
							}
							else {
								throw new ThrowableHolderException(ex);
							}
						}
						else {
							// A normal return value: will lead to a commit.
							throwableHolder.throwable = ex;
							return null;
						}
					}
					finally {
						cleanupTransactionInfo(txInfo);
					}
				});
			}
			catch (ThrowableHolderException ex) {
				throw ex.getCause();
			}
			catch (TransactionSystemException ex2) {
				if (throwableHolder.throwable != null) {
					logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
					ex2.initApplicationException(throwableHolder.throwable);
				}
				throw ex2;
			}
			catch (Throwable ex2) {
				if (throwableHolder.throwable != null) {
					logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
				}
				throw ex2;
			}

			// Check result state: It might indicate a Throwable to rethrow.
			if (throwableHolder.throwable != null) {
				throw throwableHolder.throwable;
			}
			return result;
		}
	}
}

 Spring 中支持两种事务处理的方式,分别是声明式事务与编程式事务处理。

    1. 声明式事务处理逻辑。
    • 1.1 获取事务的属性。
    • 1.2 加载配置中的 TransactionManager。
    • 1.3 不同的事务处理方式使用不同的逻辑。
    • 1.4 在目标方法执行前获取事务并收集事务信息。
    • 1.5 执行被增强方法。
    • 1.6 一旦出现异常,尝试异常处理。
    • 1.7 提交事务前的事务信息清除。
    • 1.8 提交事务。

10.3.1 创建事务

createTransactionIfNecessary()
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
	protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
			@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {

		// 如果没有名称指定则使用方法唯一标识,并使用 DelegatingTransactionAttribute 封装 txAttr
		if (txAttr != null && txAttr.getName() == null) {
			// 1. 使用 DelegatingTransactionAttribute 封装传入的 TransactionAttribute 实例,提供更多功能。
			txAttr = new DelegatingTransactionAttribute(txAttr) {
				@Override
				public String getName() {
					return joinpointIdentification;
				}
			};
		}

		TransactionStatus status = null;
		if (txAttr != null) {
			if (tm != null) {
				// 2. 获取事务
				// 获取 TransactionStatus
				status = tm.getTransaction(txAttr);
			}
			else {
				if (logger.isDebugEnabled()) {
					logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
							"] because no transaction manager has been configured");
				}
			}
		}
		// 3. 构建事务信息。
		// 根据指定的属性与 status 准备一个 TransactionInfo
		return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
	}
}

 createTransactionIfNecessary 函数主要做了以下几件事情。

  1. 使用 DelegatingTransactionAttribute 封装传入的 TransactionAttribute 实例。
  2. 获取事务。
  3. 构建事务信息。
 1 获取事务
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
	public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException {

		// Use defaults if no transaction definition given.
		TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());

		// 1. 获取事务
		// 使用的是 DataSourceTransactionManager 中的 doGetTransaction 方法,创建基于 JDBC 的事务实例。
		// 如果当前线程中存在关于 dataSource 的连接,那么直接使用。
		// 这里有一个对保存点的设置,是否开启允许保存到取决于是否设置了允许嵌入式事务。
		Object transaction = doGetTransaction();
		boolean debugEnabled = logger.isDebugEnabled();

		// 判断当前线程是否存在事务,判断依据为当前线程记录的连接不为空且连接中(connectionHolder)中的 transactionActive 属性不为空
		if (isExistingTransaction(transaction)) {
			// 2. 如果当前线程存在事务,则转向嵌套事务的处理。
			return handleExistingTransaction(def, transaction, debugEnabled);
		}

		// 3. 事务超时设置验证。
		if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
			throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
		}

		// 4. 事务 propagationBehavior 属性的设置验证。
		// 如果当前线程不存在事务,但是 propagationBehavior 却被声明为 PROPAGATION_MANDATORY 抛出异常。
		if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		// PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED 都需要新建事务
		else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
				def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
			// 空挂起
			SuspendedResourcesHolder suspendedResources = suspend(null);
			if (debugEnabled) {
				logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
			}
			try {
				// 5. 见下面方法
				// 6. 见下面方法
				// 开始事务,继续跟踪该代码
				return startTransaction(def, transaction, debugEnabled, suspendedResources);
			}
			catch (RuntimeException | Error ex) {
				resume(null, suspendedResources);
				throw ex;
			}
		}
		else {
			// Create "empty" transaction: no actual transaction, but potentially synchronization.
			if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
				logger.warn("Custom isolation level specified but no actual transaction initiated; " +
						"isolation level will effectively be ignored: " + def);
			}
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
		}
	}

	private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,
			boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {

		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);

		// 5. 构建 DefaultTransactionStatus。
		DefaultTransactionStatus status = newTransactionStatus(
				definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
		// 6. 完善 transaction,包括设置 ConnectionHolder、隔离级别、timeout、如果是新连接、绑定到当前线程。
		// 对于一些隔离级别、timeout 等功能的设置并不是由 Spring 来完成的,而是委托给底层的数据库连接去做的,而对于数据库连接的设置就是在 doBegin 函数中处理的。
		// --> DataSourceTransactionManager.doBegin
		doBegin(transaction, definition);
		// 新同步事务的设置,针对于当前线程的设置
		// 7. 将事务信息记录在当前线程中。
		prepareSynchronization(status, definition);
		return status;
	}
}

 getTransaction 核心逻辑如下。

  1. 获取事务。
  2. 如果当前线程存在事务,则转向嵌套事务的处理。
  3. 事务超时设置验证。
  4. 事务 propagationBehavior 属性的设置验证。
  5. 构建 DefaultTransactionStatus。
  6. 完善 transaction,包括设置 ConnectionHolder、隔离级别、timeout、如果是新连接、绑定到当前线程。
  7. 将事务信息记录在当前线程中。

 几个重要点以下继续跟踪。

  (1) 获取事务

 使用的是 DataSourceTransactionManager 中的 doGetTransaction 方法,创建基于 JDBC 的事务实例。
 如果当前线程中存在关于 dataSource 的连接,那么直接使用。这里有一个对保存点的设置,是否开启允许保存到取决于是否设置了允许嵌入式事务。

public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean {
	protected Object doGetTransaction() {
		DataSourceTransactionObject txObject = new DataSourceTransactionObject();
		txObject.setSavepointAllowed(isNestedTransactionAllowed());
		// 如果当前线程已经记录数据库连接则使用原有连接
		ConnectionHolder conHolder =
				(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
		// false 表示非新创建连接
		txObject.setConnectionHolder(conHolder, false);
		return txObject;
	}
}
  (6) 完善 transaction

 完善 transaction,包括设置 ConnectionHolder、隔离级别、timeout、如果是新连接、绑定到当前线程。

public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean {
	protected void doBegin(Object transaction, TransactionDefinition definition) {
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
		Connection con = null;

		try {
			// 1. 尝试获取连接。
			// 并不是每次都会获取新的连接,如果当前线程中的 connectionHolder 已经存在,则没有必要再次获取,或者,对于事务同步表示设置为 true 的需要重新获取连接。
			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();

			// 2. 设置隔离级别以及只读标识。用于负责对底层数据库连接的设置,只是包含只读标识和隔离级别的设置。
			// --> DataSourceUtils.prepareConnectionForTransaction
			Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
			txObject.setPreviousIsolationLevel(previousIsolationLevel);
			txObject.setReadOnly(definition.isReadOnly());

			// 3. 更改默认的提交设置。由 Spring 控制提交
			// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
			// so we don't want to do it unnecessarily (for example if we've explicitly
			// configured the connection pool to set it already).
			if (con.getAutoCommit()) {
				txObject.setMustRestoreAutoCommit(true);
				if (logger.isDebugEnabled()) {
					logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
				}
				con.setAutoCommit(false);
			}

			prepareTransactionalConnection(con, definition);
			// 4. 设置标志位,标识当前连接已经被事务激活。
			// 设置判断当前线程是否存在事务的依据。
			txObject.getConnectionHolder().setTransactionActive(true);

			// 5. 设置过期时间。
			int timeout = determineTimeout(definition);
			if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
				txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
			}

			// Bind the connection holder to the thread.
			if (txObject.isNewConnectionHolder()) {
				// 6. 将 connectionHolder 绑定到当前线程。
				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);
		}
	}
}

public abstract class DataSourceUtils {
	public static Integer prepareConnectionForTransaction(Connection con, @Nullable TransactionDefinition definition)
			throws SQLException {

		Assert.notNull(con, "No Connection specified");

		boolean debugEnabled = logger.isDebugEnabled();
		// 设置数据连接的只读标识
		if (definition != null && definition.isReadOnly()) {
			try {
				if (debugEnabled) {
					logger.debug("Setting JDBC Connection [" + con + "] read-only");
				}
				con.setReadOnly(true);
			}
			catch (SQLException | RuntimeException ex) {
				Throwable exToCheck = ex;
				while (exToCheck != null) {
					if (exToCheck.getClass().getSimpleName().contains("Timeout")) {
						// Assume it's a connection timeout that would otherwise get lost: e.g. from JDBC 4.0
						throw ex;
					}
					exToCheck = exToCheck.getCause();
				}
				// "read-only not supported" SQLException -> ignore, it's just a hint anyway
				logger.debug("Could not set JDBC Connection read-only", ex);
			}
		}

		// 设置数据库连接的隔离级别
		Integer previousIsolationLevel = null;
		if (definition != null && definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
			if (debugEnabled) {
				logger.debug("Changing isolation level of JDBC Connection [" + con + "] to " +
						definition.getIsolationLevel());
			}
			int currentIsolation = con.getTransactionIsolation();
			if (currentIsolation != definition.getIsolationLevel()) {
				previousIsolationLevel = currentIsolation;
				con.setTransactionIsolation(definition.getIsolationLevel());
			}
		}

		return previousIsolationLevel;
	}
}

 doBegin 核心逻辑如下。

  1. 尝试获取连接。

 并不是每次都会获取新的连接,如果当前线程中的 connectionHolder 已经存在,则没有必要再次获取,或者,对于事务同步表示设置为 true 的需要重新获取连接。
2. 设置隔离级别以及只读标识。

 只读事务隔离级别也是交给 connection 去控制的(设置 connection 的 readonly 属性)。 3. 更改默认的提交设置。

 如果事务属性是自动提交,那么需要改变这种设置,而将提交操作委托给 Spring 来处理。
4. 设置标志位,标识当前连接已经被事务激活。
5. 设置过期时间。
6. 将 connectionHolder 绑定到当前线程。
7. 将事务信息记录在当前线程中。

  (7) 将事务信息记录在当前线程中
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean {
	protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
		if (status.isNewSynchronization()) {
			TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
			TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
					definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?
							definition.getIsolationLevel() : null);
			TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
			TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
			TransactionSynchronizationManager.initSynchronization();
		}
	}
}
 2. 处理已经存在的事务

 对应 1 获取事务 中的 2. 如果当前线程存在事务,则转向嵌套事务的处理
 前面是普通事务建立的过程,但是 Spring 中支持多种事务的传播规则,比如 PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED 等,这些都是在已经存在事务的基础上进行进一步的处理,那么,对于已经存在的事务,准备操作是如何进行的呢?继续探索源码。

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
	private TransactionStatus handleExistingTransaction(
			TransactionDefinition definition, Object transaction, boolean debugEnabled)
			throws TransactionException {

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

		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);
		}

		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 {
				// 这里代码复用了
				return startTransaction(definition, transaction, debugEnabled, suspendedResources);
			}
			catch (RuntimeException | Error beginEx) {
				resumeAfterBeginException(transaction, suspendedResources, beginEx);
				throw beginEx;
			}
		}

		// 嵌入式事务的处理
		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 {
				// 有些情况是不能使用保存点操作,比如 JTA,那么建立新事务
				// Nested transaction through nested begin and commit/rollback calls.
				// Usually only for JTA: Spring synchronization might get activated here
				// in case of a pre-existing JTA transaction.
				return startTransaction(definition, transaction, debugEnabled, null);
			}
		}

		// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
		if (debugEnabled) {
			logger.debug("Participating in existing transaction");
		}
		if (isValidateExistingTransaction()) {
			if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
				Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
				if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
					Constants isoConstants = DefaultTransactionDefinition.constants;
					throw new IllegalTransactionStateException("Participating transaction with definition [" +
							definition + "] specifies isolation level which is incompatible with existing transaction: " +
							(currentIsolationLevel != null ?
									isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
									"(unknown)"));
				}
			}
			if (!definition.isReadOnly()) {
				if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
					throw new IllegalTransactionStateException("Participating transaction with definition [" +
							definition + "] is not marked as read-only but existing transaction is");
				}
			}
		}
		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
		return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
	}
}

 handleExistingTransaction 函数和普通事务由很多一样的操作,不同的主要有下面的情况。

    1. PROPAGATION_REQUIRES_NEW

 标识当前方法必须在它自己的事务里运行,一个新的事务将被启动,而如果有一个事务正在运行的话,则在这个方法运行期间被挂起。而 Spring 中对于此种传播方式的处理与新事务建立最大的不同点在于使用 suspend 方法将原事务挂起。将信息挂起的目的当然是为了在当前事务执行完毕后再将原事务还原。

    1. PROPAGATION_NESTED

 表示如果当前正有一个事务在运行中,则该方法应该运行在一个嵌套的事务中,被嵌套的事务可以独立于封装事务进行提交或回滚,如果封装事务不存在,行为就像 PROPAGATION_REQUIRES_NEW。对于嵌入式事务的处理,Spring 中主要考虑了两种方式的处理。

  • 2.1 Spring 中允许嵌入事务的时候,则首选设置保存点的方式作为异常处理的回滚。
  • 2.2 对于其他方式,比如 JTA 无法使用保存点的方式,那么处理方式于 PROPAGATION_REQUIRES_NEW 相同,而一旦出现异常,则由 Spring 的事务异常处理机制去完成后续操作。

 对于挂起操作的主要目的是记录原有事务的状态,以便于后续操作对事务的恢复。

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
	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;
		}
	}
}
 3. 准备事务信息

 对应入口是 创建事务createTransactionIfNecessary() 方法中。
 当已经建立事务连接并完成了事务信息的提取后,我们需要将所有的事务信息统一记录在 TransactionInfo 类型的实例中,这个实例包含了目标方法开始前的所有状态信息,一旦事务执行失败,Spring 会通过 TransactionInfo 类型的实例中的信息来进行回滚等后续工作。

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
	protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
			@Nullable TransactionAttribute txAttr, String joinpointIdentification,
			@Nullable TransactionStatus status) {

		TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
		if (txAttr != null) {
			// We need a transaction for this method...
			if (logger.isTraceEnabled()) {
				logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
			}
			// 记录事务状态
			// The transaction manager will flag an error if an incompatible tx already exists.
			txInfo.newTransactionStatus(status);
		}
		else {
			// The TransactionInfo.hasTransaction() method will return false. We created it only
			// to preserve the integrity of the ThreadLocal stack maintained in this class.
			if (logger.isTraceEnabled()) {
				logger.trace("No need to create transaction for [" + joinpointIdentification +
						"]: This method is not transactional.");
			}
		}

		// We always bind the TransactionInfo to the thread, even if we didn't create
		// a new transaction here. This guarantees that the TransactionInfo stack
		// will be managed correctly even if no transaction was created by this aspect.
		txInfo.bindToThread();
		return txInfo;
	}
}

10.3.2 回滚处理

 对应 TransactionAspectSupportinvokeWithinTransaction

completeTransactionAfterThrowing()
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
	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);
			}
			// 这里判断是否回滚默认的依据是抛出的异常是否是 RuntimeException 或者是 Error 的类型
			if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
				try {
					// 根据 TransactionStatus 信息进行回滚处理
					txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
				}
				catch (TransactionSystemException ex2) {
					logger.error("Application exception overridden by rollback exception", ex);
					ex2.initApplicationException(ex);
					throw ex2;
				}
				catch (RuntimeException | Error ex2) {
					logger.error("Application exception overridden by rollback exception", ex);
					throw ex2;
				}
			}
			else {
				// 如果不满足不满足回滚条件即使抛出异常也同样会提交
				// We don't roll back on this exception.
				// Will still roll back if TransactionStatus.isRollbackOnly() is true.
				try {
					txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
				}
				catch (TransactionSystemException ex2) {
					logger.error("Application exception overridden by commit exception", ex);
					ex2.initApplicationException(ex);
					throw ex2;
				}
				catch (RuntimeException | Error ex2) {
					logger.error("Application exception overridden by commit exception", ex);
					throw ex2;
				}
			}
		}
	}
}

 在对目标方法的执行过程中,一旦出现 Throwable 就会被引导至此方法处理,但是并不代表所有的 Throwable 都会被回滚处理。默认情况下,即使出现异常,数据也会被正常提交,而这个关键的地方就是在 txInfo.transactionAttribute.rollbackOn(ex) 这个函数。

 1. 回滚条件

 默认情况下 Spring 只对 RuntimeException 和 Error 两种情况回滚。我们可以拓展,或者使用事务提供的属性设置,利用注解方式设置回滚异常级别。

public class DefaultTransactionAttribute extends DefaultTransactionDefinition implements TransactionAttribute {
	public boolean rollbackOn(Throwable ex) {
		return (ex instanceof RuntimeException || ex instanceof Error);
	}
}
 2. 回滚处理
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
	public final void rollback(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");
		}

		DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
		processRollback(defStatus, false);
	}

	private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
		try {
			boolean unexpectedRollback = unexpected;

			try {
				// 1. 首先是自定义触发器的调用,包括在回滚前、完成回滚后的调用,当然完成回滚包括正常回滚于回滚过程中出现异常,
				// 自定义的触发器会根据这些信息作进一步处理,而对于触发器的注册,常见是在回调过程中提供 TransactionSynchronizationManager 类中的静态方法
				// public static void registerSynchronization(TransactionSynchronization synchronization) 直接注册。

				// 激活所有 TransactionSynchronization 中对应的方法
				triggerBeforeCompletion(status);

				// 2. 除了触发监听函数外,就是真正的回滚逻辑处理了。
				if (status.hasSavepoint()) {
					if (status.isDebug()) {
						logger.debug("Rolling back transaction to savepoint");
					}
					// 2.1 当之前已经保存的事务信息中有保存点信息的时候,使用保存点信息进行回滚。
					// 常用于嵌入式事务,对于嵌入式的事务的处理,内嵌的事务异常并不会引起外部事务的回滚。
					status.rollbackToHeldSavepoint();
				}
				else if (status.isNewTransaction()) {
					if (status.isDebug()) {
						logger.debug("Initiating transaction rollback");
					}
					// 如果当前事务为独立的新事务,则直接回退
					// 由于我们使用的是 DataSourceTransactionManager,那么 doRollback 函数会使用此类中的实现。
					doRollback(status);
				}
				else {
					// Participating in larger transaction
					if (status.hasTransaction()) {
						if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
							if (status.isDebug()) {
								logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
							}
							// 如果当前事务不是独立的事务,那么只能标记状态,等到事务链执行完毕后统一回滚
							// 当前事务信息中表明是存在事务的,又不属于以上两种清空,多数用于 JTA,只做回滚表示,等到提交的时候统一不提交。
							doSetRollbackOnly(status);
						}
						else {
							if (status.isDebug()) {
								logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
							}
						}
					}
					else {
						logger.debug("Should roll back transaction but cannot - no transaction available");
					}
					// Unexpected rollback only matters here if we're asked to fail early
					if (!isFailEarlyOnGlobalRollbackOnly()) {
						unexpectedRollback = false;
					}
				}
			}
			catch (RuntimeException | Error ex) {
				triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
				throw ex;
			}

			// 激活所有 TransactionSynchronization 中对应的方法
			triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);

			// Raise UnexpectedRollbackException if we had a global rollback-only marker
			if (unexpectedRollback) {
				throw new UnexpectedRollbackException(
						"Transaction rolled back because it has been marked as rollback-only");
			}
		}
		finally {
			// 清空记录的资源并将挂起的资源恢复
			cleanupAfterCompletion(status);
		}
	}
}

 processRollback 主要逻辑如下。

    1. 首先是自定义触发器的调用,包括在回滚前、完成回滚后的调用,当然完成回滚包括正常回滚于回滚过程中出现异常,自定义的触发器会根据这些信息作进一步处理,而对于触发器的注册,常见是在回调过程中提供 TransactionSynchronizationManager 类中的静态方法 public static void registerSynchronization(TransactionSynchronization synchronization) 直接注册。
    1. 除了触发监听函数外,就是真正的回滚逻辑处理了。
    • 2.1 当之前已经保存的事务信息中有保存点信息的时候,使用保存点信息进行回滚。常用于嵌入式事务,对于嵌入式的事务的处理,内嵌的事务异常并不会引起外部事务的回滚。
    • 2.2 当之前已经保存的事务信息中的事务为新事务,那么直接回滚。常用于单独事务的处理。对于没有保存点的回滚,Spring 同样是使用底层数据库连接提供的 API 来操作的。由于我们使用的是 DataSourceTransactionManager,那么 doRollback 函数会使用此类中的实现。
    1. 当前事务信息中表明是存在事务的,又不属于以上两种清空,多数用于 JTA,只做回滚表示,等到提交的时候统一不提交。
 3. 回滚后的信息清除
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
	private void cleanupAfterCompletion(DefaultTransactionStatus status) {
		// 1. 设置状态是对事务信息作完成标识以避免重复调用。
		status.setCompleted();
		// 2. 如果当前事务是新的同步状态,需要将绑定到当前线程的事务信息清除。
		if (status.isNewSynchronization()) {
			TransactionSynchronizationManager.clear();
		}
		if (status.isNewTransaction()) {
			// 3. 如果是新事务需要做些清除资源的工作。
			// --> DataSourceTransactionManager.doCleanupAfterCompletion
			doCleanupAfterCompletion(status.getTransaction());
		}
		if (status.getSuspendedResources() != null) {
			if (status.isDebug()) {
				logger.debug("Resuming suspended transaction after completion of inner transaction");
			}
			Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
			// 4. 如果在事务执行前有事务挂起,那么当前事务执行结束后需要将挂起事务恢复。
			resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
		}
	}

	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);
			}
		}
	}
}

public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean {
	protected void doCleanupAfterCompletion(Object transaction) {
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;

		// Remove the connection holder from the thread, if exposed.
		if (txObject.isNewConnectionHolder()) {
			// 将数据库连接从当前线程中解除绑定
			TransactionSynchronizationManager.unbindResource(obtainDataSource());
		}

		// 释放连接
		Connection con = txObject.getConnectionHolder().getConnection();
		try {
			if (txObject.isMustRestoreAutoCommit()) {
				// 恢复数据库连接的自动提交属性
				con.setAutoCommit(true);
			}
			// 重置数据库连接
			DataSourceUtils.resetConnectionAfterTransaction(
					con, txObject.getPreviousIsolationLevel(), txObject.isReadOnly());
		}
		catch (Throwable ex) {
			logger.debug("Could not reset JDBC Connection after transaction", ex);
		}

		if (txObject.isNewConnectionHolder()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Releasing JDBC Connection [" + con + "] after transaction");
			}
			// 如果当前事务时独立的新创建的事务则在事务完成时释放数据库连接
			DataSourceUtils.releaseConnection(con, this.dataSource);
		}

		txObject.getConnectionHolder().clear();
	}
}

 cleanupAfterCompletion 收尾处理工作包括如下内容。

  1. 设置状态是对事务信息作完成标识以避免重复调用。
  2. 如果当前事务是新的同步状态,需要将绑定到当前线程的事务信息清除。
  3. 如果是新事务需要做些清除资源的工作。
  4. 如果在事务执行前有事务挂起,那么当前事务执行结束后需要将挂起事务恢复。

10.3.3 事务提交

 对应 TransactionAspectSupportinvokeWithinTransaction

 commitTransactionAfterReturning()
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
	protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
		/**
		 * 当某个事务既没有保存点又不是新事务,Spring 对它的处理方式只是设置一个回滚标识。主要应用常见如下
		 * 某个事务是另一个事务的嵌入事务,但是,这些事务又不在 Spring 的管理范围内,或者无法设置保存点,那么 Spring
		 * 会通过设置回滚标识的方式来禁止提交。首先当某个嵌入事务发生回滚的时候会设置回滚标识,而等到外部事务提交时,
		 * 一旦判断出当前事务流被设置了回滚标识,则由外部事务来统一进行整体事务的回滚。
		 * 因此:当事务没有被异常捕获的时候也并不意味着一定会执行提交的过程。
		 */
		if (txInfo != null && txInfo.getTransactionStatus() != null) {
			if (logger.isTraceEnabled()) {
				logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
			}
			// --> AbstractPlatformTransactionManager.commit
			txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
		}
	}
}

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
	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");
		}

		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);
	}

	private void processCommit(DefaultTransactionStatus status) throws TransactionException {
		try {
			boolean beforeCompletionInvoked = false;

			try {
				boolean unexpectedRollback = false;
				// 预留
				prepareForCommit(status);
				// 添加的 TransactionSynchronization 中的对应方法的调用
				triggerBeforeCommit(status);
				// 添加的 TransactionSynchronization 中的对应方法的调用
				triggerBeforeCompletion(status);
				beforeCompletionInvoked = true;

				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();
					// 如果是独立的事务则直接提交
					// 通过了事务的层层把关,最后顺利地进入了提交流程
					// --> DataSourceTransactionManager.commit
					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");
				}
			}
			catch (UnexpectedRollbackException ex) {
				// can only be caused by doCommit
				triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
				throw ex;
			}
			catch (TransactionException ex) {
				// can only be caused by doCommit
				if (isRollbackOnCommitFailure()) {
					doRollbackOnCommitException(status, ex);
				}
				else {
					triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
				}
				throw ex;
			}
			catch (RuntimeException | Error ex) {
				if (!beforeCompletionInvoked) {
					// 添加的 TransactionSynchronization 中的对应方法的调用
					triggerBeforeCompletion(status);
				}
				// 提交过程中出现异常则回滚
				doRollbackOnCommitException(status, ex);
				throw ex;
			}

			// Trigger afterCommit callbacks, with an exception thrown there
			// propagated to callers but the transaction still considered as committed.
			try {
				// 添加的 TransactionSynchronization 中的对应方法的调用
				triggerAfterCommit(status);
			}
			finally {
				triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
			}

		}
		finally {
			cleanupAfterCompletion(status);
		}
	}
}

 在提交过程中也并不是直接提交的,而是考虑了诸多的方面,符合提交的条件如下。

  • 当提交状态中有保存点信息的话便不会去提交事务。
  • 当事务非新事务的时候也不会去执行提交事务操作。

 此条件主要是考虑内嵌事务的清空,对于内嵌事务,在 Spring 中正常的处理方式是将内嵌事务开始之前设置保存点,一旦内嵌事务出现异常便根据保存点信息进行回滚,但是如果没有出现异常,内嵌事务并不会单独提交,而是根据事务流由最外层事务负责提交,所以如果当前存在保存点信息便不是最外层事务,不做保存操作,对于是否是新事务的判断也是基于此考虑。

附录一、SQL 脚本

SQL 脚本
create table my_book(
	id BIGINT PRIMARY KEY not null auto_increment,
	`name` varchar(32),
	price int,
	note varchar(32)
)
Last Updated 4/9/2025, 10:09:00 PM