Spring5源码之JDBC事务

这篇文章主要介绍了Spring5源码之JDBC事务,通过源码剖析Spring5对事物是如何处理的,需要的朋友可以参考一下。

1、annotation-driven

根据配置文件annotation-driven关键字,定位到代码最终锁定类TxNamespaceHandler,在TxNamespaceHandler类中的init方法。

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

通过上面的代码,可以知道,在遇到annotation-driven的配置,Spring都会使用AnnotationDrivenBeanDefinitionParser类的parse方法进行解析。

public BeanDefinition parse(Element element, ParserContext parserContext) {
	registerTransactionalEventListenerFactory(parserContext);
	String mode = element.getAttribute("mode");
	if ("aspectj".equals(mode)) {
		// mode="aspectj"
		registerTransactionAspect(element, parserContext);
	}
	else {
		// mode="proxy"
		AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
	}
	return null;
}

在解析中存在对于mode属性的判断,根据代码,如果我们需要使用Aspectj的方式进行事务切入(Spring中的事务是以AOP为基础的)那么使用这样的配置。

<tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>

2、注册InfrastructureAdvisorAutoProxyCreator

我们以默认配置为例子进行分析,进入到AopAutoProxyConfigurer类的configureAutoProxyCreator方法。

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
	AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

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

		//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));
		// 将adviceBeanName的bean注入advisorDef的transactionAttributeSource属性中
		advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
		if (element.hasAttribute("order")) {
			// 如果配置了order属性,则加入到bean中
			advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
		}
		parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);

		//4 创建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而已,确实,这里只注册了3个bean,但是这3个bean支撑了整个的事务功能,那么这3个bean是怎么组织起来的呢?
首先,其中的两个bean被注册到了一个名为advisorDef 的bean中,advisorDef 使用BeanFactoryTransactionAttributeSourceAdvisor作为其class属性。也就是说BeanFactoryTransactionAttributeSourceAdvisor代表着当前bean。

advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);

那么如此组装的目的是什么》我们暂且留下一个悬念,接着分析代码。上面方法configureAutoProxyCreator中的第一句貌似很简单却是很重要的代码:

AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

进入这个方法:

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 static BeanDefinition registerAutoProxyCreatorIfNecessary(
		BeanDefinitionRegistry registry, @Nullable Object source) {

	return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}

对于解析来的代码流程AOP中已经有分析,上面的两个方法主要目的是注册了InfrastructureAdvisorAutoProxyCreator类型的bean,那么注册这个类的目的是什么呢?查看这个类的层次如下所示:
InfrastructureAdvisorAutoProxyCreator
从上面的层次结构中可以看到,InfrastructureAdvisorAutoProxyCreator间接实现了SmartInstantiationAwareBeanPostProcessor,而SmartInstantiationAwareBeanPostProcessor又继承自InstantiationAwareBeanPostProcessor,也就是说在Spring中,所以bean的实例化时Spring都会保证调用其postProcessAfterInstantiation方法,其实现是在父类AbstractAutoProxyCreator中实现。方法如下:

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
	if (bean != null) {
		// 根据给定的bean的class和name构建出一个key
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		if (this.earlyProxyReferences.remove(cacheKey) != bean) {
			// 如果它适合被代理,则需要封装指定的bean
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	return bean;
}

这里实现的主要目的是对指定的bean进行封装,当然首先要确定是否需要封装,检测及封装的工作都委托给了wrapIfNecessary方法进行

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

	// 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对应的增强器
  • 根据找出的增强器创建代码

3、获取对应class/method的增强器

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

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
	List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
	extendAdvisors(eligibleAdvisors);
	if (!eligibleAdvisors.isEmpty()) {
		eligibleAdvisors = sortAdvisors(eligibleAdvisors);
	}
	return eligibleAdvisors;
}

其实我们也渐渐地体会到了Spring中代码的优秀,即使是一个很复杂的逻辑,在Spring中也会被拆分成若干个小的逻辑,然后在每个方法中实现,使得每个方法的逻辑简单到我们能快速的理解,而不会像有些人开发的那样,将一大堆的都罗列到一个方法中,给后期维护人员造成巨大的困扰。同样,通过上面的方法,Spring又将任务进行了拆分,分成了获取所有增强器与增强器是否匹配两个功能点。

  • 3.1、寻找候选增强器
    在findEligibleAdvisors方法中完成的就是获取增强器的功能。
protected List<Advisor> findCandidateAdvisors() {
	Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
	return this.advisorRetrievalHelper.findAdvisorBeans();
}

public List<Advisor> findAdvisorBeans() {
	// 如果尚未缓存,定义advisor bean名称列表
	String[] advisorNames = this.cachedAdvisorBeanNames;
	if (advisorNames == null) {
		// 这里不初始化FactoryBean:我们需要保留所有常规bean未初始化,让自动代理创建器应用于它们
		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.isDebugEnabled()) {
					logger.debug("Skipping currently created advisor '" + name + "'");
				}
			}
			else {
				try {
					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.isDebugEnabled()) {
								logger.debug("Skipping advisor '" + name +
										"' with dependency on currently created bean: " + ex.getMessage());
							}
							continue;
						}
					}
					throw ex;
				}
			}
		}
	}
	return advisors;
}
  • 3.2、候选增强器中寻找到匹配项
    当找出对应的增强器后,接下来的任务就是看这些增强器是否与对应的class匹配了,当然不只是class,class内部的方法如果匹配也可以通过验证。
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 static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
	if (candidateAdvisors.isEmpty()) {
		return candidateAdvisors;
	}
	List<Advisor> eligibleAdvisors = new ArrayList<>();
	// 首先处理引介增强
	for (Advisor candidate : candidateAdvisors) {
		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) {
	if (advisor instanceof IntroductionAdvisor) {
		return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
	}
	else if (advisor instanceof PointcutAdvisor) {
		PointcutAdvisor pca = (PointcutAdvisor) advisor;
		return canApply(pca.getPointcut(), targetClass, hasIntroductions);
	}
	else {
		return true;
	}
}

当前我们分析的是对于UserService是否适用于此增强方法。那么当前的advisor就是之前查找处理的类型为BeanFactoryTransactionAttributeSourceAdvisor的bean实例,而通过类的层级结构我们知道:BeanFactoryTransactionAttributeSourceAdvisor间接实现了PointcutAdvisor接口,因此在canApply方法的第二个if判断时就会通过判断。会将BeanFactoryTransactionAttributeSourceAdvisor中的getPointcut()方法返回值作为参数继续调用canApply方法,而getPointcut()方法返回的是TransactionAttributeSourcePointcut类型的实例,对于TransactionAttributeSource这个属性大家还有印象嘛,这是在解析自定义标签时注入进去的。

private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
	@Override
	@Nullable
	protected TransactionAttributeSource getTransactionAttributeSource() {
		return transactionAttributeSource;
	}
};


public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
	Assert.notNull(pc, "Pointcut must not be null");
	if (!pc.getClassFilter().matches(targetClass)) {
		return false;
	}

	MethodMatcher methodMatcher = pc.getMethodMatcher();
	if (methodMatcher == MethodMatcher.TRUE) {
		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) {
			if (introductionAwareMethodMatcher != null ?
					introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
					methodMatcher.matches(method, targetClass)) {
				return true;
			}
		}
	}

	return false;
}

通过上面的方法大致可以理清大体脉络,首先获取对应类的所有接口并连同类本身一起遍历,遍历过程中又对类的方法再次遍历,一旦遍历成功便认为这个类适用于当前增强器。
到这里我们不禁会有疑问,对于事务的配置不仅仅局限于在方法上配置,我们都知道,在类或接口上的配置可以延续到类中的每个方法,那么,如果针对每个方法进行检测,在类本身上配置的事务属性岂不是检测不到了吗,带着这个疑问,我们进行探求matcher方法。
做匹配的时候methodMatcher.matches(method, targetClass)会使用TransactionAttributeSourcePointcut类的matches方法。

public boolean matches(Method method, @Nullable Class<?> targetClass) {
	if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
		return false;
	}
	TransactionAttributeSource tas = getTransactionAttributeSource();
	return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

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

	// 首先,看看我们是否有一个缓存的值
	Object cacheKey = getCacheKey(method, targetClass);
	TransactionAttribute cached = this.attributeCache.get(cacheKey);
	if (cached != null) {
		if (cached == NULL_TRANSACTION_ATTRIBUTE) {
			return null;
		}
		else {
			return cached;
		}
	}
	else {
		// 我们需要委托computeTransactionAttribute工作
		TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
		// 放到缓存
		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.isDebugEnabled()) {
				logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
			}
			this.attributeCache.put(cacheKey, txAttr);
		}
		return txAttr;
	}
}
  • 3.3、提取事务标签
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
	// 不允许非公共方法进行请求
	if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
		return null;
	}

	// 这个方法可以应用在接口上,但是我们需要从目标类获取睡属性。如果这个目标类是空,这个方法将会不变。
	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) {
	    // 查找接口方法
		txAttr = findTransactionAttribute(method);
		if (txAttr != null) {
			return txAttr;
		}
		// 到接口的类中去寻找。
		txAttr = findTransactionAttribute(method.getDeclaringClass());
		if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
			return txAttr;
		}
	}

	return null;
}

对于事务属性的获取规则,相信大家都已经很清楚,如果方法中存在事务属性,则使用方法上的属性,否则使用方法所在的类上的属性,如果方法所在类的属性上还是没有搜寻到对应的事务属性,那么再搜寻接口中的方法,再没有的话,最后尝试搜寻接口的类上面的声明。对于方法computeTransactionAttribute中逻辑与我们所认识的规则并无差别,但是上面方法中并没有真正的去做搜寻事务属性的逻辑,而是搭建了个执行框架,将搜寻事务属性的任务委托给了findTransactionAttribute方法去执行。

protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
	return determineTransactionAttribute(clazz);
}

protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
	for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
		TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
		if (attr != null) {
			return attr;
		}
	}
	return null;
}

this.annotationParsers是在当前类AnnotationTransactionAttributeSource初始化的时候初始话的,其中的值被加入了SpringTransactionAnnotationParser,也就是当进行属性获取的时候,其实是使用了SpringTransactionAnnotationParser类的parseTransactionAnnotation方法进行解析的。

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

至此,我们终于看到了想看的获取注解标记的代码。首先会判断当前的类是否含有Transactional注解,这是事务的基础,当然如果有的话会继续调用
parseTransactionAnnotation方法解析详细的属性。

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

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

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

	return rbta;
}

上面的方法中实现了对对应类或者方法的事务属性解析,你会在这个类中看到任何你常用或者不常用的属性。
至此,我们终于完成了事务标签的解析,我们是不是分析的太远了,似乎已经忘记了从哪里开始了。再回顾一下,我们的现在的任务是找出某个增强器是否适合于对应的类,而是否匹配的关键则在于是否从指定的类或者类中的方法找到对应的事务属性,现在,我们以UseServiceImpl为例,已经在它的接口UserService中找到了事务属性,所以,它是与事务增强器匹配的,也就是它会被事务功能修饰。
至此,事务功能的初始化工作便结束了。当判断某个bean使用于事务增强时,也就是适用于增强器BeanFactoryTransactionAttributeSourceAdvisor,没错,还是这个类,所以说,在自定义标签解析时,注入的类成为了整个事务功能的基础。
BeanFactoryTransactionAttributeSourceAdvisor作为Advisor的实现类。自然要遵从Advisor的处理方式,当代理被调用时会调用这个类的增强方法,也就是此bean的Advise,又因为在解析事务定义标签时我们把TransactionInterceptor类型的bean注入到BeanFactoryTransactionAttributeSourceAdvisor中,所以,在调用事务增强器增强的代理类时会首先执行TransactionInterceptor进行增强,同时,也就是在TransactionInterceptor类的重invoke方法中完成了整个事务的逻辑。

4、事务增强器

TransactionInterceptor支撑着整个事务功能的架构,逻辑还是相对复杂的,那么现在外面的切入正题来分析此拦截器是如何实现事务特性的。TransactionInterceptor类继承自MethodInterceptor,所以调用该类是从其invoke方法开始的,首先预览下这个方法。

public Object invoke(MethodInvocation invocation) throws Throwable {
	Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

	// 获取对应的事务属性
	return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}


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

	// 如果事务属性为null,则该方法是非事务性的。
	TransactionAttributeSource tas = getTransactionAttributeSource();
	final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
	final PlatformTransactionManager tm = determineTransactionManager(txAttr);
	final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

	if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
		// 使用getTransaction和提交/回滚调用的标准事务界定。
		TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

		Object retVal;
		try {
			// 这是一个around声明:调用链中的下一个拦截器,这通常会导致调用目标对象。
			retVal = invocation.proceedWithInvocation();
		}
		catch (Throwable ex) {
		    // 异常回滚
			completeTransactionAfterThrowing(txInfo, ex);
			throw ex;
		}
		finally {
			// 清除信息
			cleanupTransactionInfo(txInfo);
		}
		// 提交事务
		commitTransactionAfterReturning(txInfo);
		return retVal;
	}

	else {
		final ThrowableHolder throwableHolder = new ThrowableHolder();
		// 编程式事务处理
		try {
			Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
				TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
				try {
					return invocation.proceedWithInvocation();
				}
				catch (Throwable ex) {
					if (txAttr.rollbackOn(ex)) {
						if (ex instanceof RuntimeException) {
							throw (RuntimeException) ex;
						}
						else {
							throw new ThrowableHolderException(ex);
						}
					}
					else {
						throwableHolder.throwable = ex;
						return null;
					}
				}
				finally {
					cleanupTransactionInfo(txInfo);
				}
			});

			if (throwableHolder.throwable != null) {
				throw throwableHolder.throwable;
			}
			return result;
		}
		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;
		}
	}
}

从上面的方法中,我们尝试整理下事务处理的脉络,在Spring中支持两种事务处理的方式,分别是声明式事务处理与编程式事务处理,两者相对于开发人员来讲差别很大,但是对于Spring中的实现来讲,大同小异。在invoke中我们也可以看到这两中方式的实现。考虑到对事务的应用比声明式的事务处理使用起来方便,也相对流行些。我们就以此种方式进行分析。对于声明式的事务处理主要有以下几个步骤。

  • 获取事务属性。
    对于事务处理来说,最基础便是获取事务的属性了,这是支撑整个事务功能的基石,如果没有事务属性,其他功能也无从谈起。

  • 加载配置中配置的TransactionManager。

  • 不同的事务处理方式使用不同的逻辑。
    对于声明式事务的处理与编程式事务的处理,第一点区别是在于事务属性上,因为编程式的事务处理不需要有事务属性,第二点区别是TransactionManager。

  • 在目标方法执行前获取事务并非收集事务信息。

  • 执行目标方法。

  • 一旦出现异常,尝试异常处理。并不是所有的异常,Spring都会讲其回滚,默认只对RuntimeException回滚。

  • 提交事务前的事务信息清除。

  • 提交事务。

  • 4.1、创建事务

protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
		@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {

	// 如果没有名字指定则使用方法唯一标识,并使用DelegatingTransactionAttribute封装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) {
			// 获取TransactionStatus
			status = tm.getTransaction(txAttr);
		}
		else {
			if (logger.isDebugEnabled()) {
				logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
						"] because no transaction manager has been configured");
			}
		}
	}
	// 根据给定的属性和状态准备一个TransactionInfo
	return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}

createTransactionIfNecessary方法主要做了这样几件事情

  • 使用DelegatingTransactionAttribute封装传入的TransactionAttribute 实例。
  • 获取事务。
  • 构建事务信息。
    下面从以上三个部分进行详细的阐述。
    获取事务:Spring中使用getTransaction来处理事务的准备工作,包括事务获取以及信息的构建。
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
	Object transaction = doGetTransaction();
	// 缓存调试标志以避免重复检查
	boolean debugEnabled = logger.isDebugEnabled();

	if (definition == null) {
		// 如果没有给出事务定义,则使用默认值
		definition = new DefaultTransactionDefinition();
	}

	// 判断当前线程是否存在事务,判断依据为当前线程记录的连接不为空且连接中(connectionHolder)中的transactionActive属性不为空。
	if (isExistingTransaction(transaction)) {
		// 现有事务发现->检查传播行为,以找出如何行为
		return handleExistingTransaction(definition, transaction, debugEnabled);
	}

	// 事务超时设置验证
	if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
		throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
	}
	// 如果当前线程不存在事务,但是propagationBehavior却被声明PROPAGATION_MANDATORY抛出异常
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
		throw new IllegalTransactionStateException(
				"No existing transaction found for transaction marked with propagation 'mandatory'");
	}
	else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
			definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
			definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
		// PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED都需要新建事务
		// 空挂起
		SuspendedResourcesHolder suspendedResources = suspend(null);
		if (debugEnabled) {
			logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
		}
		try {
			boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
			DefaultTransactionStatus status = newTransactionStatus(
					definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
			// 构造transaction,包括设置ConnectionHolder、隔离级别、timeout,如果是新连接,绑定到当前线程。
			doBegin(transaction, definition);
			// 新同步事务的设置,针对于当前线程的设置。
			prepareSynchronization(status, definition);
			return status;
		}
		catch (RuntimeException | Error ex) {
			resume(null, suspendedResources);
			throw ex;
		}
	}
	else {
		if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
			logger.warn("Custom isolation level specified but no actual transaction initiated; " +
					"isolation level will effectively be ignored: " + definition);
		}
		boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
		return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
	}
}

数据库连接设置doBegin

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

		// 更改自动提交设置,由Spring控制提交。
		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);
	}
}

设置隔离级别prepareConnectionForTransaction

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

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

	// 设置数据连接的只读标识
	if (definition != null && definition.isReadOnly()) {
		try {
			if (logger.isDebugEnabled()) {
				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();
			}
			logger.debug("Could not set JDBC Connection read-only", ex);
		}
	}

	// 设置数据库连接的隔离级别
	Integer previousIsolationLevel = null;
	if (definition != null && definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
		if (logger.isDebugEnabled()) {
			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;
}

将事务信息记录在当前线程中

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

处理已经存在的事务

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 {
			boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
			DefaultTransactionStatus status = newTransactionStatus(
					definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
			doBegin(transaction, definition);
			prepareSynchronization(status, definition);
			return status;
		}
		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()) {
			// 如果没有可以使用保存点的方式控制事务回滚,那么在嵌入式事务的建立保存点。
	    			DefaultTransactionStatus status =
					prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
			status.createAndHoldSavepoint();
			return status;
		}
		else {
			// 有些情况是不能使用保存点操作,比如JTA,那么建立新事务
			boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
			DefaultTransactionStatus status = newTransactionStatus(
					definition, transaction, true, newSynchronization, debugEnabled, null);
			doBegin(transaction, definition);
			prepareSynchronization(status, definition);
			return status;
		}
	}

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

事务挂起操作

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) {
			doResumeSynchronization(suspendedSynchronizations);
			throw ex;
		}
	}
	else if (transaction != null) {
		Object suspendedResources = doSuspend(transaction);
		return new SuspendedResourcesHolder(suspendedResources);
	}
	else {
		return null;
	}
}

准备事务信息

protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
			@Nullable TransactionAttribute txAttr, String joinpointIdentification,
			@Nullable TransactionStatus status) {

	TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
	if (txAttr != null) {
		if (logger.isTraceEnabled()) {
			logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
		}
		// 记录事务状态
		txInfo.newTransactionStatus(status);
	}
	else {
		if (logger.isTraceEnabled()) {
			logger.trace("No need to create transaction for [" + joinpointIdentification +
					"]: This method is not transactional.");
		}
	}

	txInfo.bindToThread();
	return txInfo;
}
  • 4.2、回滚处理
    之前已经完成了目标方法运行前的事务准备工作,而这些准备工作最大的目的无非是对于程序没有按照我们期待的那样进行,也就是出现特定的错误。那么当出现错误的时候,Spring是怎么对数据进行恢复的呢?
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);
		}
		// 当抛出异常时首先判断当前是否存在事务,这是基础依据
		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 {
			// 如果不满足回滚条件即使抛出异常也同样会提交
			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都会被回滚处理,比如我们常用的Exception。默认是不会被处理的。默认情况下,即使出现异常,数据也会被正常提交,而这个关键的地方就是在txInfo.transactionAttribute.rollbackOn(ex)这个方法。
回滚条件

public boolean rollbackOn(Throwable ex) {
	return (ex instanceof RuntimeException || ex instanceof Error);
}

看到了吗?默认情况下Spring中的事务异常处理机制只对RuntimeException 和Error两种情况感兴趣,当然你可以通过扩展来改变,不过,我们最常用的还是使用事务提供的属性设置,利用注解方式的使用,例如:

@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)

回滚处理
当然,一旦符合回滚条件,那么Spring就会将程序引导至回滚处理函数中。

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 {
			// 激活所有的TransactionSynchronization中对应的方法
			triggerBeforeCompletion(status);

			if (status.hasSavepoint()) {
				if (status.isDebug()) {
					logger.debug("Rolling back transaction to savepoint");
				}
				// 如果有保存点,也就是当前事务为单独的线程则会退到保存点
				status.rollbackToHeldSavepoint();
			}
			else if (status.isNewTransaction()) {
				if (status.isDebug()) {
					logger.debug("Initiating transaction rollback");
				}
				// 如果当前事务为独立的新事务,则直接回退
				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");
						}
						// 如果当前事务不是独立事务,那么只能标记状态,等到事务链执行完毕统一回滚
						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);
	}
}
  • 4.3、事务提交
    之前我们分析了Spring的事务异常处理机制,那么事务的执行并没有出现任何的异常。也就意味着事务可以走正常事务提交的流程了。
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());
	}
}

在真正的数据提交之前,还需要做个判断。不知道大家还有没有印象,在我们分析事务异常处理规则的时候,当某个事务既然没有保存点又不是新事务,Spring对它的处理方式只是设置一个回滚标识。这个回滚标识在这里就会派上用场了。

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);
			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();
				// 如果是独立的事务则直接提交
				doCommit(status);
			}
			else if (isFailEarlyOnGlobalRollbackOnly()) {
				unexpectedRollback = status.isGlobalRollbackOnly();
			}

			if (unexpectedRollback) {
				throw new UnexpectedRollbackException(
						"Transaction silently rolled back because it has been marked as rollback-only");
			}
		}
		catch (UnexpectedRollbackException ex) {

			triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
			throw ex;
		}
		catch (TransactionException ex) {
			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;
		}

		try {
			// 添加TransactionSynchronization中对应的方法调用
			triggerAfterCommit(status);
		}
		finally {
			triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
		}

	}
	finally {
		cleanupAfterCompletion(status);
	}
}

如果程序流通过了事务的层次把关,最后顺利地进入了提交流程,那么同样,Spring会将事务提交的操作引导至底层数据库连接的API进行事务提交。

protected void doCommit(DefaultTransactionStatus status) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
	Connection con = txObject.getConnectionHolder().getConnection();
	if (status.isDebug()) {
		logger.debug("Committing JDBC transaction on Connection [" + con + "]");
	}
	try {
		con.commit();
	}
	catch (SQLException ex) {
		throw new TransactionSystemException("Could not commit JDBC transaction", ex);
	}
}

如果您觉得有帮助,欢迎收藏点赞哦 ~ ~ 多谢~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值