Spring源码深度解析:十八、事务实现② - ProxyTransactionManagementConfiguration

一、前言

文章目录:Spring源码深度解析:文章目录

由于事务的源码和前篇的Aop源码逻辑很类似,所以本篇中某些内容不会展开去讲解,建议先阅读完 全集目录中的Aop部分,再来阅读本文会更好理解。

上篇中我们讲到@EnableTransactionManagement引入了两个类:AutoProxyRegistrarProxyTransactionManagementConfiguration

  • AutoProxyRegistrar: 主要是注册了InfrastructureAdvisorAutoProxyCreator自动代理创建器。而 InfrastructureAdvisorAutoProxyCreator的逻辑基本上和 Aop 的逻辑相同
  • ProxyTransactionManagementConfiguration: 注册了事务实现的核心 Bean,包括 BeanFactoryTransactionAttributeSourceAdvisor、TransactionAttributeSource、TransactionInterceptor等。

在上一篇中我们分析了AutoProxyRegistrar的作用,本篇则来分析一下ProxyTransactionManagementConfiguration的逻辑过程。

二、 ProxyTransactionManagementConfiguration

ProxyTransactionManagementConfiguration代码如下,并没有逻辑,就是将几个Bean注入的到容器中。不过这几个bean可都是关键bean,所以我们需要对其中的bean进行分析。

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

	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		advisor.setTransactionAttributeSource(transactionAttributeSource());
		advisor.setAdvice(transactionInterceptor());
		if (this.enableTx != null) {
			advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
		}
		return advisor;
	}

	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
		return new AnnotationTransactionAttributeSource();
	}

	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionInterceptor transactionInterceptor() {
		TransactionInterceptor interceptor = new TransactionInterceptor();
		interceptor.setTransactionAttributeSource(transactionAttributeSource());
		if (this.txManager != null) {
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}
}
  • BeanFactoryTransactionAttributeSourceAdvisor: 事务的增强器,该方法是否开始事务,是否需要代理该类都在该类中判断
  • TransactionAttributeSource : 保存了事务相关的一些信息资源。
  • TransactionInterceptor : 事务拦截器,事务生成代理类时使用的代理拦截器,编写了事务的规则

1. BeanFactoryTransactionAttributeSourceAdvisor

@SuppressWarnings("serial")
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

	@Nullable
	private TransactionAttributeSource transactionAttributeSource;

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


	/**
	 * Set the transaction attribute source which is used to find transaction
	 * attributes. This should usually be identical to the source reference
	 * set on the transaction interceptor itself.
	 * @see TransactionInterceptor#setTransactionAttributeSource
	 */
	public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
		this.transactionAttributeSource = transactionAttributeSource;
	}

	/**
	 * Set the {@link ClassFilter} to use for this pointcut.
	 * Default is {@link ClassFilter#TRUE}.
	 */
	public void setClassFilter(ClassFilter classFilter) {
		this.pointcut.setClassFilter(classFilter);
	}

	@Override
	public Pointcut getPointcut() {
		return this.pointcut;
	}

}

这个根据上面的分析,我们可以知道这个是事务判断的核心,BeanFactoryTransactionAttributeSourceAdvisorAdvisor子类,那么我们可以知道其中有两个关键属性:Pointcut(判断是否可以作用于当前方法) 和 Advice(作用于当前方法的具体逻辑)。

通过 Aop文章的分析我们可以知道,Advisor判断一个方法是否匹配,是通过其Pointcut.matchs属性来判断的。然后我们通过上面的代码,发现其Pointcut的实现类是TransactionAttributeSourcePointcut,也就是说,一个方法是否需要使用事务,是通过 TransactionAttributeSourcePointcut#matches方法判断的。

1.1. TransactionAttributeSourcePointcut

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

	protected TransactionAttributeSourcePointcut() {
		setClassFilter(new TransactionAttributeSourceClassFilter());
	}


	@Override
	public boolean matches(Method method, Class<?> targetClass) {
		// 调用 TransactionAttributeSource.getTransactionAttribute方法来匹配
		TransactionAttributeSource tas = getTransactionAttributeSource();
		return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
	}

	... 省略一些无关代码
	
	/**
	 * Obtain the underlying TransactionAttributeSource (may be {@code null}).
	 * To be implemented by subclasses.
	 */
	@Nullable
	protected abstract TransactionAttributeSource getTransactionAttributeSource();

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

		@Override
		public boolean matches(Class<?> clazz) {
			// 如果是一些基础类,则返回false
			if (TransactionalProxy.class.isAssignableFrom(clazz) ||
					PlatformTransactionManager.class.isAssignableFrom(clazz) ||
					PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
				return false;
			}
			// 调用 TransactionAttributeSource.isCandidateClass 方法来匹配
			TransactionAttributeSource tas = getTransactionAttributeSource();
			return (tas == null || tas.isCandidateClass(clazz));
		}
	}

}

Aop中我们总结了 Pointcut 匹配的需要满足下面两个条件:

  1. pc.getClassFilter().matches(targetClass)返回true
  2. pc.getMethodMatcher().matches(method, targetClass)返回true
    如下图,具体实现在AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class<?>, boolean)中,这里第二点不考虑,因为在这里不会为True
    在这里插入图片描述
    通过TransactionAttributeSourcePointcut的代码我们可以发现,上面两个条件的关键
    可以转换成
  3. 调用TransactionAttributeSource.isCandidateClass方法来匹配 :TransactionAttributeSourceClassFilter#matches中调用了该方法
  4. 调用TransactionAttributeSource.getTransactionAttribute方法来匹配
    TransactionAttributeSource正是我们在ProxyTransactionManagementConfiguration中注入的 AnnotationTransactionAttributeSource

ProxyTransactionManagementConfiguration#transactionAttributeSource()

	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
		return new AnnotationTransactionAttributeSource();
	}

2. AnnotationTransactionAttributeSource

经过上面的分析,我们知道了主要逻辑在isCandidateClassgetTransactionAttribute方法中,也就是一个Bean是否需要事务代理需要通过下面两个方法的校验。因此我们下面来看看这两个方法的实现

2.1 AnnotationTransactionAttributeSource#isCandidateClass

isCandidateClass主要是判断是否是候选类,即当前的的注解解析器annotationParsers是否可以解析当前类。annotationParsers的初始化在其构造函数中,在初始化的过程中中添加了SpringTransactionAnnotationParser,我们后面的事务注解解析就是通过SpringTransactionAnnotationParser进行的解析。

这里annotationParsers有三种解析类型:

  • SpringTransactionAnnotationParser :即我们默认的事务解析器,解析的注解是 org.springframework.transaction.annotation.Transactional
  • JtaTransactionAnnotationParser:解析的注解是javax.transaction.Transactional
  • Ejb3TransactionAnnotationParser:解析的注解是javax.ejb.TransactionAttribute
	private final Set<TransactionAnnotationParser> annotationParsers;
	...
	
	public AnnotationTransactionAttributeSource() {
		this(true);
	}
	...
	public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
		this.publicMethodsOnly = publicMethodsOnly;
		// 可以看到,无论什么场景 SpringTransactionAnnotationParser 都是必定存在的解析器
		if (jta12Present || ejb3Present) {
			this.annotationParsers = new LinkedHashSet<>(4);
			this.annotationParsers.add(new SpringTransactionAnnotationParser());
			if (jta12Present) {
				this.annotationParsers.add(new JtaTransactionAnnotationParser());
			}
			if (ejb3Present) {
				this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
			}
		}
		else {
			this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
		}
	}
	
	@Override	
	public boolean isCandidateClass(Class<?> targetClass) {
		for (TransactionAnnotationParser parser : this.annotationParsers) {
			// 这里是SpringTransactionAnnotationParser  类型, SpringTransactionAnnotationParser#isCandidateClass 中判断了目标类是否存在  org.springframework.transaction.annotation.Transactional 注解
			if (parser.isCandidateClass(targetClass)) {
				return true;
			}
		}
		return false;
	}

SpringTransactionAnnotationParser#isCandidateClass中判断了目标类是否存在 org.springframework.transaction.annotation.Transactional注解,如果存在,这里会返回true,通过校验

2.2 AbstractFallbackTransactionAttributeSource#getTransactionAttribute

getTransactionAttribute方法的实现在其父类AbstractFallbackTransactionAttributeSource中实现的

// 获取事务属性,如果
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
		// 判断声明类是否是 Object 
		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;
		}
	}

	...	
	// 解析事务注解属性
	protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
		// Don't allow no-public methods as required.
		// 如果只允许解析public 方法 && 当前方法不是 publissh
		if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
			return null;
		}

		// The method may be on an interface, but we need attributes from the target class.
		// If the target class is null, the method will be unchanged.
		// method 代表接口中的方法,specificMethod  方法代表实现类中的方法
		Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

		// First try is the method in the target class.
		// 寻找实现类方法的事务属性,即类方法是否有声明事务属性
		TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
		if (txAttr != null) {
			return txAttr;
		}

		// Second try is the transaction attribute on the target class.
		// 在实现类上是否有事务属性的声明
		txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
		if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
			return txAttr;
		}
		// 如果存在接口方法,则从接口方法中尝试去获取事务属性
		if (specificMethod != method) {
			// Fallback is to look at the original method.
			txAttr = findTransactionAttribute(method);
			if (txAttr != null) {
				return txAttr;
			}
			// Last fallback is the class of the original method.
			txAttr = findTransactionAttribute(method.getDeclaringClass());
			if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
				return txAttr;
			}
		}
		// 都没得到则返回没有得到
		return null;
	}

这里的逻辑还是很清楚的

  1. 从实现类方法上获取事务注解,若获取到则返回
  2. 从实现类上获取事务注解,若获取到则返回
  3. 如果存在接口方法,则从接口方法中获取事务注解,若获取到则返回
  4. 若仍未获取到,则返回null,认为当前方法没有被注解修饰
2.2.1 AnnotationTransactionAttributeSource#findTransactionAttribute(java.lang.reflect.Method)

在上面的代码中,我们注意到一个方法findTransactionAttribute。上面代码就是通过 findTransactionAttribute方法来寻找事务注解属性的。而findTransactionAttribute的实现在AnnotationTransactionAttributeSource中。其实现代码如下

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

可以看到AnnotationTransactionAttributeSource中获取事务注解是通过 TransactionAnnotationParser#parseTransactionAnnotation方法去解析的,而一开始我们就说过annotationParsers在构造函数中添加了SpringTransactionAnnotationParser。我们来看看SpringTransactionAnnotationParser进行了怎么样的解析。

2.2.2 SpringTransactionAnnotationParser#parseTransactionAnnotation(java.lang.reflect.AnnotatedElement)

到这里,我们终于看到了事务注解的描述,这里就是解析事务注解的各种属性信息了

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

我们的分析到这里,就已经可以知道了Spring 中对事务注解的解析过程,逻辑基本和 Spring Aop 类似。

  1. @EnableTransactionManagement通过引入 TransactionManagementConfigurationSelector注册了AutoProxyRegistrarProxyTransactionManagementConfiguration两个类。
  2. AutoProxyRegistrar中注册了InfrastructureAdvisorAutoProxyCreator自动代理创建器
  3. InfrastructureAdvisorAutoProxyCreator中拦截bean的创建过程,通过 BeanFactoryTransactionAttributeSourceAdvisor来判断bean中是否有事务注解,有则进行代理。

在上面的逻辑中,我们似乎没有发现Spring事务代理的具体过程,实际上代理的过程是在 TransactionInterceptor中。

3. TransactionInterceptor

在 Aop 的分析文章中,我们知道了无论是 Jdk代理还是 Cglib代理,其增强实现都是调用Advisor中的Advice实现。BeanFactoryTransactionAttributeSourceAdvisor作为Advisor的实现类,自然要遵从Advisor的处理方式,当代理被调用时会调用这个类的增强方法,也就是此bean 的Advice,而在解析事务标签是,我们把TransactionInterceptor注入到了 BeanFactoryTransactionAttributeSourceAdvisor中,所以调用事务增强器增强代理类的时会首先执行TransactionInterceptor进行增强,同时也就是TransactionInterceptor#invoke完成了整个事务的逻辑。

所以我们这里自然要看TransactionInterceptor#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);
	}

可以看到核心逻辑都在invokeWithinTransaction方法中,这里调用的 invokeWithinTransaction方法 实际是 TransactionAspectSupport#invokeWithinTransaction方法。所以下面我们来看看 TransactionAspectSupport#invokeWithinTransaction方法的具体实现

3.1. TransactionAspectSupport#invokeWithinTransaction

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

		// If the transaction attribute is null, the method is non-transactional.
		// 获取事务数据源,这里获取的数据源就是在  TransactionInterceptor 注入的时候的设置的属性transactionAttributeSource = AnnotationTransactionAttributeSource。
		// 在 ProxyTransactionManagementConfiguration 中完成	
		TransactionAttributeSource tas = getTransactionAttributeSource();
		// 1. 获取对应的事务属性
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
		// 2. 获取一个合适的 TransactionManager 
		final TransactionManager tm = determineTransactionManager(txAttr);
		// 3. 对于反应式事务的处理
		// 从Spring Framework 5.2 M2开始,Spring通过ReactiveTransactionManagerSPI 支持响应式/反应式事务管理
		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);
		}
		// 判断 tm是否是 PlatformTransactionManager 类型,是则强转,不是则抛出异常
		PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
		// 构造方法的唯一标识( 全路径了类名.方法)
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
		// 4. 对不同事务情景的处理
		// 声明式事务的处理
		// 如果txAttr为空或者tm 属于非CallbackPreferringPlatformTransactionManager,执行目标增强
		// 在TransactionManager上,CallbackPreferringPlatformTransactionManager实现PlatformTransactionManager接口,暴露出一个方法用于执行事务处理中的回调
		if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
			// 5.如果有必要,创建事务信息。主要由于事务的传播属性,所以这里并不一定会创建事务
			TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

			Object retVal;
			try {
				// This is an around advice: Invoke the next interceptor in the chain.
				// This will normally result in a target object being invoked.
				// 6. 执行被增强的方法
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				// target invocation exception
				// 7. 异常回滚
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
				// 8. 提交之前清除事务信息
				cleanupTransactionInfo(txInfo);
			}

			if (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);
				}
			}
			// 9.提交事务
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}
		// 编程式事务(CallbackPreferringPlatformTransactionManager)的处理。这里的逻辑基本都被封装了
		else {
			final ThrowableHolder throwableHolder = new ThrowableHolder();
			try {
				// 直接调用execute 方法。由于事务的提交回滚等操作都已经封装好了,所以这里并没有对事务进行详细的操作。
				Object result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
					// 准备事务信息
					TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
					try {
						// 执行方法
						Object retVal = invocation.proceedWithInvocation();
						if (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);
					}
				});

				// Check result state: It might indicate a Throwable to rethrow.
				if (throwableHolder.throwable != null) {
					throw throwableHolder.throwable;
				}
				return result;
			}
			catch (ThrowableHolderException ex) {
				throw ex.getCause();
			}
			catch (TransactionSystemException ex2) {
				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支持声明式事务和编程式事务两种处理。两者的实现本质基本相同。在invoke方法中我们也可以看到这两种方式的实现,通常我们使用的都是通过 @Transactional注解修饰的声明式事务,所以我们下面主要分析 声明式事务 的处理过程。

  1. 获取事务属性TransactionAttributeTransactionAttribute中包含 传播属性,timeout等事务属性信息。如果是使用@Transactional注解,这个解析过程是在AnnotationTransactionAttributeSource#findTransactionAttribute(java.lang.reflect.Method) 中完成,具体看 篇2中有解释。
  2. 加载配置中的TrancationManager, 事务管理器,是事务实现的基础,我们这里获取到的是DataSourceTransactionManager
  3. 对反应式事务的处理。
  4. 不同事务处理方式使用不同的逻辑。在上面的代码中主要是两种情况,一是声明式事务,这种情况是通过@Transactional注解修饰方法来表示开启事务。另一种情况是编程式事务,即可以通过xml方式或者配置类方式来进行完成事务功能,其实TransactionTemplate的实现就是编程式事务,但通过TransactionTemplate并不会走到这个逻辑,这里的编程式事务应该单独是通过xml或者配置类方式来配置的。
    对于声明式事务的处理和编程式事务的处理,区别主要在两点。一是事务属性上,因为编程式事务是不需要事务属性的,二是TransactionManager的不同,CallbackPreferringPlatformTransactionManager实现了PlatformTransactionManager接口,暴露了一个方法用于执行事务处理中的回调。所以这两种方式都可以作为事务处理方式的判断。
  5. 在目标方法执行前获取事务并收集事务信息。
    事务信息与事务属性并不相同,也就是TransactionInfoTransactionAttribute并不相同,TransactionInfo 中包含TransactionAttribute信息,并且处理TransactionAttribute之外还有其他事物信息,比如PlatformTransactionManager以及TransactionStatus相关信息。
  6. 执行目标方法
  7. 如果出现异常,则进行回滚。这里需要注意,默认的情况下只有RuntimeException异常才会执行回滚。可以通过@Transactional(rollbackFor = Exception.class)的方式来指定触发回滚的异常
  8. 提交事务前的事务信息清除
  9. 提交事务
  10. 若是 编程式事务,则直接执行execute方法即可,这里就不再讲解。

注:PlatformTransactionManagerReactiveTransactionManager 二者都是为了实现事务,PlatformTransactionManager在内部进行事务执行流程的封装,并且暴露出来一个execute方法用于执行事务的具体信息,TransactionTemplate的声明式事务就是基于此实现的。而ReactiveTransactionManager则是比较原始的,需要我们自己来实现事务的整个逻辑。

上面比较笼统的讲了事务的实现,下面们主要分析以下三个方法,也是事务的的关键流程:

  • 事务的创建 - createTransactionIfNecessary
  • 事务的回滚 - completeTransactionAfterThrowing
  • 事务的提交 - commitTransactionAfterReturning

以上:内容部分参考
《Spring源码深度解析》
如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值