spring tx 事务核心流程源码分析

今天我们来看下spring 的 tx 模块的核心流程。

1. 实例

配置一个启动事务管理类,配置一个数据源事务管理器:

	@Configuration
	@EnableTransactionManagement
	static class DefaultTxManagerNameConfig {

		@Bean
		PlatformTransactionManager transactionManager(DataSource dataSource) {
			return new DataSourceTransactionManager(dataSource);
		}
	}

配置一个数据源、JdbcFooRepository 类

	@Configuration
	static class Config {

		@Bean
		FooRepository fooRepository() {
			JdbcFooRepository repos = new JdbcFooRepository();
			repos.setDataSource(dataSource());
			return repos;
		}

		@Bean
		DataSource dataSource() {
			return new EmbeddedDatabaseBuilder()
				.setType(EmbeddedDatabaseType.HSQL)
				.build();
		}
	}

基础的 DAO 类,在 findAll() 方法上标注 @Transactional 注解

	interface FooRepository {

		List<Object> findAll();
	}

	static class JdbcFooRepository implements FooRepository {

		public void setDataSource(DataSource dataSource) {
		}

		@Override
		@Transactional
		public List<Object> findAll() {
			ArrayList<Object> result = new ArrayList<>();
			for (int i1 = 0; i1 < 10; i1++) {
				int random = (int) (Math.random() * 100);
				result.add(random);
			}
			return result;
		}
	}

最后配置一个测试类:

public class EnableTransactionManagementIntegrationTests {
  
  @Test
	void repositoryIsTxProxy_withDefaultTxManagerName() {
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class, DefaultTxManagerNameConfig.class);
		FooRepository repo = ctx.getBean(FooRepository.class);
		List<Object> all = repo.findAll();
		System.out.println("all = " + all);
	}

}

这样就配置了一个使用事务注解支持事务的方法的例子了。

2. 分析

我们从 DefaultTxManagerNameConfig 上的 @EnableTransactionManagement 开始看:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

	/**
	 * 指定使用什么代理模式(true 为 cglib 代理,false 为 jdk 代理)
	 *
	 * Indicate whether subclass-based (CGLIB) proxies are to be created ({@code true}) as
	 * opposed to standard Java interface-based proxies ({@code false}). The default is
	 * {@code false}. <strong>Applicable only if {@link #mode()} is set to
	 * {@link AdviceMode#PROXY}</strong>.
	 * <p>Note that setting this attribute to {@code true} will affect <em>all</em>
	 * Spring-managed beans requiring proxying, not just those marked with
	 * {@code @Transactional}. For example, other beans marked with Spring's
	 * {@code @Async} annotation will be upgraded to subclass proxying at the same
	 * time. This approach has no negative impact in practice unless one is explicitly
	 * expecting one type of proxy vs another, e.g. in tests.
	 */
	boolean proxyTargetClass() default false;

	/**
	 * 通知的模式,代理模式或者 aspectj,一般是使用代理模式。
	 * 注意代理模式只允许调用拦截,通过在本类中的本地调用不能被拦截;
	 * 一个 Transactional 注解在一个本地调用的方法上将会被 spring 的拦截器忽略,甚至不会再这种场景中出现。
	 * 对于拦截更多高级
	 *
	 * Indicate how transactional advice should be applied.
	 * <p><b>The default is {@link AdviceMode#PROXY}.</b>
	 * Please note that proxy mode allows for interception of calls through the proxy
	 * only. Local calls within the same class cannot get intercepted that way; an
	 * {@link Transactional} annotation on such a method within a local call will be
	 * ignored since Spring's interceptor does not even kick in for such a runtime
	 * scenario. For a more advanced mode of interception, consider switching this to
	 * {@link AdviceMode#ASPECTJ}.
	 */
	AdviceMode mode() default AdviceMode.PROXY;

	/**
	 * Indicate the ordering of the execution of the transaction advisor
	 * when multiple advices are applied at a specific joinpoint.
	 * <p>The default is {@link Ordered#LOWEST_PRECEDENCE}.
	 */
	int order() default Ordered.LOWEST_PRECEDENCE;

}

这个类有三个属性,proxyTargetClass、mode、order,分别表示:是否使用 cglib 代理、通知的模式(PROXY 或者 ASPECTJ)、排序。

它还使用了 @Import(TransactionManagementConfigurationSelector.class) 注解,导入了 TransactionManagementConfigurationSelector 类:

/**
 * 在导入 @Configuration 注解类时候,根据选择 EnableTransactionManagement 的 mode,来选择
 * AbstractTransactionManagementConfiguration 类合适的子类,
 *
 * Selects which implementation of {@link AbstractTransactionManagementConfiguration}
 * should be used based on the value of {@link EnableTransactionManagement#mode} on the
 * importing {@code @Configuration} class.
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @since 3.1
 * @see EnableTransactionManagement
 * @see ProxyTransactionManagementConfiguration
 * @see TransactionManagementConfigUtils#TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME
 * @see TransactionManagementConfigUtils#JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME
 */
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

	/**
	 * Returns {@link ProxyTransactionManagementConfiguration} or
	 * {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY}
	 * and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()},
	 * respectively.
	 */
	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
		switch (adviceMode) {
			case PROXY:
				return new String[] {AutoProxyRegistrar.class.getName(),
						ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
				return new String[] {determineTransactionAspectClass()};
			default:
				return null;
		}
	}

	private String determineTransactionAspectClass() {
		return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
				TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
				TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
	}

}

看下它的类图结构:

TransactionManagementConfigurationSelector

这个类继承了 AdviceModeImportSelector 类,它是一个 ImportSelector 导入选择器,重写了 selectImports() 方法,通过 adviceMode 来返回一组类的名称,我们一般使用 AdviceMode.PROXY,可以看到它会返回 AutoProxyRegistrar.classs 和 ProxyTransactionManagementConfiguration.class 这两个类的名称。

我们回顾下 ImportSelector 类,它的 selectImports() 方法是在 org.springframework.context.annotation.ConfigurationClassParser#processImports 中进行调用的。它是在 spring 容器启动时,执行 bean 工厂注册器后置处理器时,调用了 ConfigurationClassParser 配置类解析器的解析扫描 @Configuration 注解的类的 bean 定义流程中执行的。

2.1 AutoProxyRegistrar

接着继续看 AutoProxyRegistrar.classs 这个类,它的类图:

AutoProxyRegistrar

它实现为:

/**
 * 针对当前的 BeanDefinitionRegistry 作为一个合适的基于 @Enable* 注解标有 mode 和 proxyTargetClass 的属性,
 * 设置到正确的值。
 *
 * Registers an auto proxy creator against the current {@link BeanDefinitionRegistry}
 * as appropriate based on an {@code @Enable*} annotation having {@code mode} and
 * {@code proxyTargetClass} attributes set to the correct values.
 *
 * @author Chris Beams
 * @since 3.1
 * @see org.springframework.cache.annotation.EnableCaching
 * @see org.springframework.transaction.annotation.EnableTransactionManagement
 */
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	private final Log logger = LogFactory.getLog(getClass());

	/**
	 * 注册bean 定义
	 *
	 * Register, escalate, and configure the standard auto proxy creator (APC) against the
	 * given registry. Works by finding the nearest annotation declared on the importing
	 * {@code @Configuration} class that has both {@code mode} and {@code proxyTargetClass}
	 * attributes. If {@code mode} is set to {@code PROXY}, the APC is registered; if
	 * {@code proxyTargetClass} is set to {@code true}, then the APC is forced to use
	 * subclass (CGLIB) proxying.
	 * <p>Several {@code @Enable*} annotations expose both {@code mode} and
	 * {@code proxyTargetClass} attributes. It is important to note that most of these
	 * capabilities end up sharing a {@linkplain AopConfigUtils#AUTO_PROXY_CREATOR_BEAN_NAME
	 * single APC}. For this reason, this implementation doesn't "care" exactly which
	 * annotation it finds -- as long as it exposes the right {@code mode} and
	 * {@code proxyTargetClass} attributes, the APC can be registered and configured all
	 * the same.
	 */
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		boolean candidateFound = false;
		Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
		for (String annType : annTypes) {
			AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
			if (candidate == null) {
				continue;
			}
			// 获取模式
			Object mode = candidate.get("mode");
			// 获取代理目标类
			Object proxyTargetClass = candidate.get("proxyTargetClass");
			if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
					Boolean.class == proxyTargetClass.getClass()) {
				candidateFound = true;
				// 使用代理模式
				if (mode == AdviceMode.PROXY) {
					AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
					if ((Boolean) proxyTargetClass) {
						// 强制自动代理创建器使用类代理,proxyTargetClass
						AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
						return;
					}
				}
			}
		}
		if (!candidateFound && logger.isInfoEnabled()) {
			String name = getClass().getSimpleName();
			logger.info(String.format("%s was imported but no annotations were found " +
					"having both 'mode' and 'proxyTargetClass' attributes of type " +
					"AdviceMode and boolean respectively. This means that auto proxy " +
					"creator registration and configuration may not have occurred as " +
					"intended, and components may not be proxied as expected. Check to " +
					"ensure that %s has been @Import'ed on the same class where these " +
					"annotations are declared; otherwise remove the import of %s " +
					"altogether.", name, name, name));
		}
	}

}

它是一个 ImportBeanDefinitionRegistrar 类型,导入 bean 定义注册器,实现了 registerBeanDefinitions() 方法,这个方法做的事情:

  1. 获取导入类的注解元数据;
  2. 获取 mode 注解属性、proxyTargetClass 注解属性;
  3. 根据它们的值,注册一个名称为 org.springframework.aop.config.internalAutoProxyCreator,值为 InfrastructureAdvisorAutoProxyCreator 类型的 bean 定义;
  4. 以及bean 定义的 proxyTargetClass 属性。

它的这个方法是在 org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromRegistrars 处调用的,也是属于配置类后置处理器注册已经将 bean 定义解析为配置类的流程中。

2.2 InfrastructureAdvisorAutoProxyCreator

看下 InfrastructureAdvisorAutoProxyCreator 类,它的类图:

InfrastructureAdvisorAutoProxyCreator

它的实现:

/**
 * 自动代理创建器,仅仅考虑基础的增强器 beans,忽略其他应用程序定义的增强器
 *
 * Auto-proxy creator that considers infrastructure Advisor beans only,
 * ignoring any application-defined Advisors.
 *
 * @author Juergen Hoeller
 * @since 2.0.7
 */
@SuppressWarnings("serial")
public class InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {

	@Nullable
	private ConfigurableListableBeanFactory beanFactory;


	@Override
	protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		super.initBeanFactory(beanFactory);
		this.beanFactory = beanFactory;
	}

	@Override
	protected boolean isEligibleAdvisorBean(String beanName) {
		// 判断是否是一个合格的增强器,@Role(BeanDefinition.ROLE_INFRASTRUCTURE) bean 定义的角色是基础类
		return (this.beanFactory != null && this.beanFactory.containsBeanDefinition(beanName) &&
				this.beanFactory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE);
	}

}

这个类它和 spring aop 中的 AnnotationAwareAspectJAutoProxyCreator 类很像,没错!它们都是共同继承了 AbstractAdvisorAutoProxyCreator 类型,间接的实现了 BeanPostProcessor 的 postProcessBeforeInstantiation() 方法和 postProcessAfterInitialization() 方法。这两个方法主要是对代理对象进行检查以及初始化,并且进行创建其代理。

2.3 ProxyTransactionManagementConfiguration

再看下 ProxyTransactionManagementConfiguration 类:

/**
 * 这是一个 @Configuration 类,它注册了 spring 基础类,这些类时启动基于代理的注解驱动的事务管理器的必要类。
 *
 * {@code @Configuration} class that registers the Spring infrastructure beans
 * necessary to enable proxy-based annotation-driven transaction management.
 *
 * @author Chris Beams
 * @author Sebastien Deleuze
 * @since 3.1
 * @see EnableTransactionManagement
 * @see TransactionManagementConfigurationSelector
 */
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

	/**
	 * 注册一个内部的事务增强器 org.springframework.transaction.config.internalTransactionAdvisor
	 *
	 * @param transactionAttributeSource
	 * @param transactionInterceptor
	 * @return
	 */
	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
			TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {

		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		// 设置事务属性源
		advisor.setTransactionAttributeSource(transactionAttributeSource);
		// 设置通知事务拦截器
		advisor.setAdvice(transactionInterceptor);
		if (this.enableTx != null) {
			advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
		}
		return advisor;
	}

	/**
	 * 定义一个注解事务属性源
	 *
	 * @return
	 */
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
		// 注解的事务属性源
		return new AnnotationTransactionAttributeSource();
	}

	/**
	 * 定义一个事务拦截器
	 *
	 * @param transactionAttributeSource
	 * @return
	 */
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
		TransactionInterceptor interceptor = new TransactionInterceptor();
		// 设置事务属性源
		interceptor.setTransactionAttributeSource(transactionAttributeSource);
		if (this.txManager != null) {
			// 设置事务管理器
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}

}

这个类引入了三个 bean:AnnotationTransactionAttributeSource、TransactionInterceptor、BeanFactoryTransactionAttributeSourceAdvisor。

2.4 AnnotationTransactionAttributeSource

它是一个注解事务属性源,看下它的类图:

AnnotationTransactionAttributeSource

它的实现:

/**
 * Implementation of the
 * {@link org.springframework.transaction.interceptor.TransactionAttributeSource}
 * interface for working with transaction metadata in JDK 1.5+ annotation format.
 *
 * <p>This class reads Spring's JDK 1.5+ {@link Transactional} annotation and
 * exposes corresponding transaction attributes to Spring's transaction infrastructure.
 * Also supports JTA 1.2's {@link javax.transaction.Transactional} and EJB3's
 * {@link javax.ejb.TransactionAttribute} annotation (if present).
 * This class may also serve as base class for a custom TransactionAttributeSource,
 * or get customized through {@link TransactionAnnotationParser} strategies.
 *
 * @author Colin Sampaleanu
 * @author Juergen Hoeller
 * @since 1.2
 * @see Transactional
 * @see TransactionAnnotationParser
 * @see SpringTransactionAnnotationParser
 * @see Ejb3TransactionAnnotationParser
 * @see org.springframework.transaction.interceptor.TransactionInterceptor#setTransactionAttributeSource
 * @see org.springframework.transaction.interceptor.TransactionProxyFactoryBean#setTransactionAttributeSource
 */
@SuppressWarnings("serial")
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
		implements Serializable {

	private static final boolean jta12Present;

	private static final boolean ejb3Present;

	static {
		ClassLoader classLoader = AnnotationTransactionAttributeSource.class.getClassLoader();
		jta12Present = ClassUtils.isPresent("javax.transaction.Transactional", classLoader);
		ejb3Present = ClassUtils.isPresent("javax.ejb.TransactionAttribute", classLoader);
	}

	private final boolean publicMethodsOnly;

	private final Set<TransactionAnnotationParser> annotationParsers;


	/**
	 * Create a default AnnotationTransactionAttributeSource, supporting
	 * public methods that carry the {@code Transactional} annotation
	 * or the EJB3 {@link javax.ejb.TransactionAttribute} annotation.
	 */
	public AnnotationTransactionAttributeSource() {
		this(true);
	}

	/**
	 * Create a custom AnnotationTransactionAttributeSource, supporting
	 * public methods that carry the {@code Transactional} annotation
	 * or the EJB3 {@link javax.ejb.TransactionAttribute} annotation.
	 * @param publicMethodsOnly whether to support public methods that carry
	 * the {@code Transactional} annotation only (typically for use
	 * with proxy-based AOP), or protected/private methods as well
	 * (typically used with AspectJ class weaving)
	 */
	public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
		this.publicMethodsOnly = publicMethodsOnly;
		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());
		}
	}

	/**
	 * Create a custom AnnotationTransactionAttributeSource.
	 * @param annotationParser the TransactionAnnotationParser to use
	 */
	public AnnotationTransactionAttributeSource(TransactionAnnotationParser annotationParser) {
		this.publicMethodsOnly = true;
		Assert.notNull(annotationParser, "TransactionAnnotationParser must not be null");
		this.annotationParsers = Collections.singleton(annotationParser);
	}

	/**
	 * Create a custom AnnotationTransactionAttributeSource.
	 * @param annotationParsers the TransactionAnnotationParsers to use
	 */
	public AnnotationTransactionAttributeSource(TransactionAnnotationParser... annotationParsers) {
		this.publicMethodsOnly = true;
		Assert.notEmpty(annotationParsers, "At least one TransactionAnnotationParser needs to be specified");
		this.annotationParsers = new LinkedHashSet<>(Arrays.asList(annotationParsers));
	}

	/**
	 * Create a custom AnnotationTransactionAttributeSource.
	 * @param annotationParsers the TransactionAnnotationParsers to use
	 */
	public AnnotationTransactionAttributeSource(Set<TransactionAnnotationParser> annotationParsers) {
		this.publicMethodsOnly = true;
		Assert.notEmpty(annotationParsers, "At least one TransactionAnnotationParser needs to be specified");
		this.annotationParsers = annotationParsers;
	}


	@Override
	public boolean isCandidateClass(Class<?> targetClass) {
		for (TransactionAnnotationParser parser : this.annotationParsers) {
			if (parser.isCandidateClass(targetClass)) {
				return true;
			}
		}
		return false;
	}

	@Override
	@Nullable
	protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
		// 从类上找事务属性
		return determineTransactionAttribute(clazz);
	}

	@Override
	@Nullable
	protected TransactionAttribute findTransactionAttribute(Method method) {
		// 从方法上找事务属性
		return determineTransactionAttribute(method);
	}

	/**
	 * Determine the transaction attribute for the given method or class.
	 * <p>This implementation delegates to configured
	 * {@link TransactionAnnotationParser TransactionAnnotationParsers}
	 * for parsing known annotations into Spring's metadata attribute class.
	 * Returns {@code null} if it's not transactional.
	 * <p>Can be overridden to support custom annotations that carry transaction metadata.
	 * @param element the annotated method or class
	 * @return the configured transaction attribute, or {@code null} if none was found
	 */
	@Nullable
	protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
		// 遍历所有的注解解析器
		for (TransactionAnnotationParser parser : this.annotationParsers) {
			// 从事务注解解析器上解析
			TransactionAttribute attr = parser.parseTransactionAnnotation(element);
			if (attr != null) {
				return attr;
			}
		}
		return null;
	}

	/**
	 * By default, only public methods can be made transactional.
	 */
	@Override
	protected boolean allowPublicMethodsOnly() {
		return this.publicMethodsOnly;
	}


	@Override
	public boolean equals(@Nullable Object other) {
		if (this == other) {
			return true;
		}
		if (!(other instanceof AnnotationTransactionAttributeSource)) {
			return false;
		}
		AnnotationTransactionAttributeSource otherTas = (AnnotationTransactionAttributeSource) other;
		return (this.annotationParsers.equals(otherTas.annotationParsers) &&
				this.publicMethodsOnly == otherTas.publicMethodsOnly);
	}

	@Override
	public int hashCode() {
		return this.annotationParsers.hashCode();
	}

}

这个类间接的实现了 TransactionAttributeSource 接口,间接的实现了它的 org.springframework.transaction.interceptor.TransactionAttributeSource#isCandidateClass 和 org.springframework.transaction.interceptor.TransactionAttributeSource#getTransactionAttribute 方法,这两个方法都是在 org.springframework.aop.support.AopUtils#canApply 这个方法中被调用的,AopUtils#canApply 方法又是在上面提到的实现了 BeanPostProcessor 接口的 postProcessAfterInitialization() 方法的 InfrastructureAdvisorAutoProxyCreator 类所实现。

2.4.1 判断是否候选类 isCandidateClass()

isCandidateClass() 方法:它在 bean 初始化之后,在获取通知和增强器的方法逻辑 getAdvicesAndAdvisorsForBean() 中调用 findAdvisorsThatCanApply(),再调用 canApply() 方法,根据 BeanFactoryTransactionAttributeSourceAdvisor 增强器,获取事务属性源切点 BeanFactoryTransactionAttributeSourceAdvisor#pointcut TransactionAttributeSourcePointcut 类型,获取切点 AnnotationTransactionAttributeSource 类,间接的调用它的 isCandidateClass() 方法,最后调用 SpringTransactionAnnotationParser 的 isCandidateClass() 方法,由 AnnotationUtils 工具类判断目标类是否有 @Transactional 来判断是否符合合格的类;

2.4.2 获取事务属性 TransactionAttribute 类型 getTransactionAttribute()

它实现 org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#getTransactionAttribute:

	/**
	 * 为这个方法执行获取事务属性。如果方法属性没有找到,默认是为类的事务属性。
	 *
	 * Determine the transaction attribute for this method invocation.
	 * <p>Defaults to the class's transaction attribute if no method attribute is found.
	 * @param method the method for the current invocation (never {@code null})
	 * @param targetClass the target class for this invocation (may be {@code null})
	 * @return a TransactionAttribute for this method, or {@code null} if the method
	 * is not transactional
	 */
	@Override
	@Nullable
	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 dta = (DefaultTransactionAttribute) txAttr;
					dta.setDescriptor(methodIdentification);
					dta.resolveAttributeStrings(this.embeddedValueResolver);
				}
				if (logger.isTraceEnabled()) {
					logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
				}
				// 加入到缓存
				this.attributeCache.put(cacheKey, txAttr);
			}
			return txAttr;
		}
	}


	/**
	 * Determine a cache key for the given method and target class.
	 * <p>Must not produce same key for overloaded methods.
	 * Must produce same key for different instances of the same method.
	 * @param method the method (never {@code null})
	 * @param targetClass the target class (may be {@code null})
	 * @return the cache key (never {@code null})
	 */
	protected Object getCacheKey(Method method, @Nullable Class<?> targetClass) {
		return new MethodClassKey(method, targetClass);
	}

	/**
	 * 计算属性源
	 *
	 * Same signature as {@link #getTransactionAttribute}, but doesn't cache the result.
	 * {@link #getTransactionAttribute} is effectively a caching decorator for this method.
	 * <p>As of 4.1.8, this method can be overridden.
	 * @since 4.1.8
	 * @see #getTransactionAttribute
	 */
	@Nullable
	protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
		// 不允许非 public 修饰的方法
		// Don't allow no-public methods as required.
		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 = 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;
	}

getTransactionAttribute() 方法:也是在上述 isCandidateClass() 方法调用逻辑中的 org.springframework.aop.support.AopUtils#canApply 方法中,通过 TransactionAttributeSourcePointcut 类调用 matches() 方法,再调用 getTransactionAttributeSource() 方法获取事务属性源,最后获取事务属性 TransactionAttribute。它主要是在 org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#getTransactionAttribute 这个方法中实现的逻辑:

  1. 先从缓存中查找事务属性;
  2. 计算事务属性 computeTransactionAttribute();
    1. 判断方法是否是 public 修饰的;
    2. 获取目标方法;
    3. 先从目标类上的方法查找 @Transcation 注解;
    4. 然后尝试从目标方法所在类上查找 @Transcation 注解;
    5. 在从接口的方法上查找 @Transcation 注解;
    6. 最后再从接口类上的查找 @Transcation 注解;
  3. 保存到缓存。

2.4.3 查找事务属性 findTransactionAttribute()

这个方法是一个重载方法,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#findTransactionAttribute(java.lang.Class<?>)org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#findTransactionAttribute(java.lang.reflect.Method),最终都调用到了 org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#determineTransactionAttribute 方法:

	protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
		// 遍历所有的注解解析器
		for (TransactionAnnotationParser parser : this.annotationParsers) {
			// 从事务注解解析器上解析
			TransactionAttribute attr = parser.parseTransactionAnnotation(element);
			if (attr != null) {
				return attr;
			}
		}
		return null;
	}

它通过事务注解解析器来解析:org.springframework.transaction.annotation.SpringTransactionAnnotationParser#parseTransactionAnnotation(java.lang.reflect.AnnotatedElement)

	@Override
	@Nullable
	public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
		// 解析 @Transactional 注解
		AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
				element, Transactional.class, false, false);
		if (attributes != null) {
			// 真正的开始解析
			return parseTransactionAnnotation(attributes);
		}
		else {
			return null;
		}
	}

	/**
	 * 开始解析事务注解
	 *
	 * @param attributes
	 * @return
	 */
	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());
		String timeoutString = attributes.getString("timeoutString");
		Assert.isTrue(!StringUtils.hasText(timeoutString) || rbta.getTimeout() < 0,
				"Specify 'timeout' or 'timeoutString', not both");
		rbta.setTimeoutString(timeoutString);

		// 是否只读
		rbta.setReadOnly(attributes.getBoolean("readOnly"));
		// 事务名称
		rbta.setQualifier(attributes.getString("value"));
		rbta.setLabels(Arrays.asList(attributes.getStringArray("label")));

		// 回滚规则
		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;
	}

可以看到它最终会返回一个 RuleBasedTransactionAttribute 类型的事务属性。

2.4.4 事务定义 RuleBasedTransactionAttribute

它的类图:

RuleBasedTransactionAttribute

这个类实现了 TransactionDefinition 接口,我们看下这个接口类图是:

TransactionDefinition

这个类主要定义了事务的一些基本属性信息,有事务名称、事务传播行为、事务隔离级别、超时时间、是否只读。

2.5 BeanFactoryTransactionAttributeSourceAdvisor

这个类的类图:

BeanFactoryTransactionAttributeSourceAdvisor

它的实现:

/**
 * bean 工厂事务属性源增强器
 *
 * Advisor driven by a {@link TransactionAttributeSource}, used to include
 * a transaction advice bean for methods that are transactional.
 *
 * @author Juergen Hoeller
 * @since 2.5.5
 * @see #setAdviceBeanName
 * @see TransactionInterceptor
 * @see TransactionAttributeSourceAdvisor
 */
@SuppressWarnings("serial")
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

	@Nullable
	private TransactionAttributeSource transactionAttributeSource;

	/**
	 * 事务属性源切点
	 */
	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
		@Override
		@Nullable
		protected TransactionAttributeSource getTransactionAttributeSource() {
			// 获取事务属性源 AnnotationTransactionAttributeSource 类型
			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;
	}

}

它是一个 PointcutAdvisor 类型实现类,切点增强器,它也是实现 getPointcut() 方法,返回一个 TransactionAttributeSourcePointcut 类,这个类在上面的 canApply() 方法中用到了。

2.6 TransactionInterceptor

这个类的类图:

TransactionInterceptor

再看下它的实现:

@SuppressWarnings("serial")
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {

	/**
	 * Create a new TransactionInterceptor.
	 * <p>Transaction manager and transaction attributes still need to be set.
	 * @see #setTransactionManager
	 * @see #setTransactionAttributes(java.util.Properties)
	 * @see #setTransactionAttributeSource(TransactionAttributeSource)
	 */
	public TransactionInterceptor() {
	}

	/**
	 * Create a new TransactionInterceptor.
	 * @param ptm the default transaction manager to perform the actual transaction management
	 * @param tas the attribute source to be used to find transaction attributes
	 * @since 5.2.5
	 * @see #setTransactionManager
	 * @see #setTransactionAttributeSource
	 */
	public TransactionInterceptor(TransactionManager ptm, TransactionAttributeSource tas) {
		setTransactionManager(ptm);
		setTransactionAttributeSource(tas);
	}

	/**
	 * Create a new TransactionInterceptor.
	 * @param ptm the default transaction manager to perform the actual transaction management
	 * @param tas the attribute source to be used to find transaction attributes
	 * @see #setTransactionManager
	 * @see #setTransactionAttributeSource
	 * @deprecated as of 5.2.5, in favor of
	 * {@link #TransactionInterceptor(TransactionManager, TransactionAttributeSource)}
	 */
	@Deprecated
	public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) {
		setTransactionManager(ptm);
		setTransactionAttributeSource(tas);
	}

	/**
	 * Create a new TransactionInterceptor.
	 * @param ptm the default transaction manager to perform the actual transaction management
	 * @param attributes the transaction attributes in properties format
	 * @see #setTransactionManager
	 * @see #setTransactionAttributes(java.util.Properties)
	 * @deprecated as of 5.2.5, in favor of {@link #setTransactionAttributes(Properties)}
	 */
	@Deprecated
	public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) {
		setTransactionManager(ptm);
		setTransactionAttributes(attributes);
	}

	/**
	 * 事务拦截器进行拦截调用
	 *
	 * @param invocation the method invocation joinpoint
	 * @return
	 * @throws Throwable
	 */
	@Override
	@Nullable
	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);
	}


	//---------------------------------------------------------------------
	// Serialization support
	//---------------------------------------------------------------------

	private void writeObject(ObjectOutputStream oos) throws IOException {
		// Rely on default serialization, although this class itself doesn't carry state anyway...
		oos.defaultWriteObject();

		// Deserialize superclass fields.
		oos.writeObject(getTransactionManagerBeanName());
		oos.writeObject(getTransactionManager());
		oos.writeObject(getTransactionAttributeSource());
		oos.writeObject(getBeanFactory());
	}

	private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
		// Rely on default serialization, although this class itself doesn't carry state anyway...
		ois.defaultReadObject();

		// Serialize all relevant superclass fields.
		// Superclass can't implement Serializable because it also serves as base class
		// for AspectJ aspects (which are not allowed to implement Serializable)!
		setTransactionManagerBeanName((String) ois.readObject());
		setTransactionManager((PlatformTransactionManager) ois.readObject());
		setTransactionAttributeSource((TransactionAttributeSource) ois.readObject());
		setBeanFactory((BeanFactory) ois.readObject());
	}

}

TransactionInterceptor 是一个实现了 MethodInterceptor 接口的 invoke() 方法,对方法执行进行拦截,间接调用了 org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction 方法:

	/**
	 * 用于基于环绕通知子类的总代表,委派到该类的其他几个模板方法。能够处理 CallbackPreferringPlatformTransactionManager
	 * 和常规的 PlatformTransactionManager 实现类以及 ReactiveTransactionManager 实现类,对于无返回类型。
	 *
	 * General delegate for around-advice-based subclasses, delegating to several other template
	 * methods on this class. Able to handle {@link CallbackPreferringPlatformTransactionManager}
	 * as well as regular {@link PlatformTransactionManager} implementations and
	 * {@link ReactiveTransactionManager} implementations for reactive return types.
	 * @param method the Method being invoked
	 * @param targetClass the target class that we're invoking the method on
	 * @param invocation the callback to use for proceeding with the target invocation
	 * @return the return value of the method, if any
	 * @throws Throwable propagated from the target invocation
	 */
	@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.
		// 获取事务属性源
		TransactionAttributeSource tas = getTransactionAttributeSource();
		// 获取事务属性
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
		// 获取项目中事务管理器,一般是 DataSourceTransactionManager 类
		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);
		}

		PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
		// 获取我们需要切入的方法(也就是我们标识了 @Transactional 注解的方法)
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

		if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
			// 事务信息
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
			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.
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				// 抛出异常进行回滚
				// target invocation exception
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
				// 清理事务信息
				cleanupTransactionInfo(txInfo);
			}

			if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
				// Set rollback-only in case of Vavr failure matching our rollback rules...
				TransactionStatus status = txInfo.getTransactionStatus();
				if (status != null && txAttr != null) {
					retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
				}
			}

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

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

梳理下这个方法的核心流程:

  1. 获取事务属性源 TransactionAttributeSource;
  2. 获取事务属性 TransactionAttribute,这里会返回 RuleBasedTransactionAttribute 类型;
  3. 获取事务管理器 TransactionManager;
  4. 获取方法描述器 joinpointIdentification;
  5. 执行 createTransactionIfNecessary() 方法,创建事务信息 TransactionInfo;
  6. 执行 invocation.proceedWithInvocation() 执行器方法,这将会执行调用链中下一个拦截器,如果没有拦截,则执行目标方法;
  7. 遇到异常之后执行 completeTransactionAfterThrowing() 方法,进行回滚或提交操作,然后抛出异常;
  8. 执行 cleanupTransactionInfo() 方法,清除事务信息;
  9. 没有异常的情况,执行 commitTransactionAfterReturning() 提交事务;
  10. 返回执行结果。

2.6.1 创建事务信息 createTransactionIfNecessary()

看下 org.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessary 这个创建事务信息方法:

	/**
	 * 根据给定的事务属性来创建一个事务。
	 *
	 * Create a transaction if necessary based on the given TransactionAttribute.
	 * <p>Allows callers to perform custom TransactionAttribute lookups through
	 * the TransactionAttributeSource.
	 * @param txAttr the TransactionAttribute (may be {@code null})
	 * @param joinpointIdentification the fully qualified method name
	 * (used for monitoring and logging purposes)
	 * @return a TransactionInfo object, whether or not a transaction was created.
	 * The {@code hasTransaction()} method on TransactionInfo can be used to
	 * tell if there was a transaction created.
	 * @see #getTransactionAttributeSource()
	 */
	@SuppressWarnings("serial")
	protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
			@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {

		// 包装事务属性,名称为方法描述符
		// If no name specified, apply method identification as transaction name.
		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) {
				// 获取事务,返回事务状态
				status = tm.getTransaction(txAttr);
			}
			else {
				if (logger.isDebugEnabled()) {
					logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
							"] because no transaction manager has been configured");
				}
			}
		}
		// 准备事务信息
		return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
	}

它的逻辑:

  1. 通过事务管理器获取事务状态 getTransaction();
  2. 准备事务信息 prepareTransactionInfo(),创建事务信息 TransactionInfo 类;

2.6.1.1 获取事务状态 getTransaction()

看下如何获取事务状态信息:org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction

	/**
	 * 实现处理传播行为的方法,委派到 doGetTransaction、isExistingTransaction、doBegin 方法
	 *
	 * This implementation handles propagation behavior. Delegates to
	 * {@code doGetTransaction}, {@code isExistingTransaction}
	 * and {@code doBegin}.
	 * @see #doGetTransaction
	 * @see #isExistingTransaction
	 * @see #doBegin
	 */
	@Override
	public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException {

		// 获取事务定义
		// Use defaults if no transaction definition given.
		TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());

		// 获取事务对象
		Object transaction = doGetTransaction();
		boolean debugEnabled = logger.isDebugEnabled();

		// 判断是否存在事务
		if (isExistingTransaction(transaction)) {
			// Existing transaction found -> check propagation behavior to find out how to behave.
			// 处理已存在的事务
			return handleExistingTransaction(def, transaction, debugEnabled);
		}

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

		// 判断事务传播行为 MANDATORY 必须的
		// No existing transaction found -> check propagation behavior to find out how to proceed.
		if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		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 {
				// 开始一个新的事务
				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);
		}
	}

它的逻辑:

  1. 执行 doGetTransaction() 方法,获取事务对象,返回一个 DataSourceTransactionObject 类型对象;
  2. 判断是否存在事务 isExistingTransaction();
  3. 如果存在事务,执行 handleExistingTransaction() 方法,处理已存在的事务,结束;
  4. 判断事务是否超时,判断正确的传播行为;
  5. 判断传播行为如果是支持当前事务的(REQUIRED、REQUIRED_NEW、NESTED),先执行 suspend() 方法,挂起当前事务,然后执行 startTransaction() 开启一个新事物,结束;
  6. 否则执行 prepareTransactionStatus() 方法,创建一个空的事务,结束。

2.6.1.2 获取 DataSourceTransactionObject 事务对象 doGetTransaction()

看下它的实现 org.springframework.jdbc.datasource.DataSourceTransactionManager#doGetTransaction:

	/**
	 * 获取事务对象
	 *
	 * @return
	 */
	@Override
	protected Object doGetTransaction() {
		// 创建一个数据源事务对象
		DataSourceTransactionObject txObject = new DataSourceTransactionObject();
		// 设置允许嵌套事务(保存点)
		txObject.setSavepointAllowed(isNestedTransactionAllowed());
		// 获取连接持有器
		ConnectionHolder conHolder =
				(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
		// 为数据源事务对象设置连接持有器(首次获取为空)
		txObject.setConnectionHolder(conHolder, false);
		return txObject;
	}

可以看到事务对象是一个 DataSourceTransactionObject 类型的对象,它的类图结构:

DataSourceTransactionObject

它拥有的属性有:连接持有器、是否允许保存点、是否只读、前一个事务隔离级别、是否新的连接持有器、是否仅支持回滚、是否必须还原自动提交属性等等。

上面的 doGetTransaction() 方法逻辑:

  1. 创建一个 DataSourceTransactionObject 类型对象;
  2. 设置是否允许保存点(即是否允许嵌套事务);
  3. 获取连接持有器(这里是从线程本地化中获取的,首次获取为 null);
  4. 为事务对象设置连接持有器。

2.6.1.3 判断是否存在事务 isExistingTransaction()

我们先看下它是如何判断事务是否存在的:org.springframework.jdbc.datasource.DataSourceTransactionManager#isExistingTransaction

	/**
	 * 判断是否存在事务
	 *
	 * @param transaction the transaction object returned by doGetTransaction
	 * @return
	 */
	@Override
	protected boolean isExistingTransaction(Object transaction) {
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
		// 事务有连接持有器 && 连接持有器中的事务是活跃的
		return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
	}
  1. 事务对象是否有连接持有器;
  2. 连接持有器中的事务是否是活跃的。

2.6.1.4 处理已存在的事务 handleExistingTransaction()

接着看处理已经存在的事务 org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction 方法:

	/**
	 * 为一个已经存在的事务,创建一个事务状态
	 *
	 * Create a TransactionStatus for an existing transaction.
	 */
	private TransactionStatus handleExistingTransaction(
			TransactionDefinition definition, Object transaction, boolean debugEnabled)
			throws TransactionException {

		// 判断传播行为:never 抛出异常
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
			throw new IllegalTransactionStateException(
					"Existing transaction found for transaction marked with propagation 'never'");
		}

		// 传播行为是 NOT_SUPPORTED 不执行事务
		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);
		}

		// 传播行为:REQUIRES_NEW 开启一个新的事务
		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;
			}
		}

		// 传播行为:NESTED 嵌套事务
		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 {
				// 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");
				}
			}
		}
		// 传播行为:不是 NEVER,准备事务状态
		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
		return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
	}

逻辑:

  1. 判断传播行为,不同的传播行为执行不同的逻辑;
  2. 传播行为是 NOT_SUPPORTED 不执行事务;
    1. 先执行 suspend() 挂起当前事务;
    2. 执行 prepareTransactionStatus() 准备事务。
  3. 传播行为是 REQUIRES_NEW 开启新事物;
    1. 先执行 suspend() 挂起当前事务;
    2. 执行 startTransaction() 开启一个新事物。
  4. 传播行为是 NESTED 嵌套事务;
    1. 判断是否为嵌套事务使用保存点;
    2. 如果不是,则执行 startTransaction() 方法,开启一个新事物;
    3. 如果是,则先执行 prepareTransactionStatus() 创建一个新的事务状态 DefaultTransactionStatus,然后执行事务状态的 createAndHoldSavepoint() 创建保存点,返回。
  5. 验证现有的事务;
  6. 其他的传播行为,执行 prepareTransactionStatus() 方法,准备事务状态。

2.6.1.5 挂起事务 suspend()

挂起事务是 org.springframework.transaction.support.AbstractPlatformTransactionManager#suspend 方法中实现的:

	/**
	 * 挂起给定的事务。首先挂起事务同步,然后委派 doSuspend 模板方法。
	 *
	 * Suspend the given transaction. Suspends transaction synchronization first,
	 * then delegates to the {@code doSuspend} template method.
	 * @param transaction the current transaction object
	 * (or {@code null} to just suspend active synchronizations, if any)
	 * @return an object that holds suspended resources
	 * (or {@code null} if neither transaction nor synchronization active)
	 * @see #doSuspend
	 * @see #resume
	 */
	@Nullable
	protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
		// 判断是否同步是活跃的
		if (TransactionSynchronizationManager.isSynchronizationActive()) {
			// 执行挂起同步
			List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
			try {
				Object suspendedResources = null;
				if (transaction != null) {
					// 对给定的事务进行挂起,返回一个当前连接资源
					suspendedResources = doSuspend(transaction);
				}
				// 清除当前事务信息
				// 当前事务名称
				String name = TransactionSynchronizationManager.getCurrentTransactionName();
				TransactionSynchronizationManager.setCurrentTransactionName(null);
				// 是否只读
				boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
				TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
				// 隔离级别
				Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
				TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
				// 是哦福活跃
				boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
				TransactionSynchronizationManager.setActualTransactionActive(false);
				// 创建新一个挂起资源持有器,把当前事务信息都保存起来
				return new SuspendedResourcesHolder(
						suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
			}
			catch (RuntimeException | Error ex) {
				// doSuspend failed - original transaction is still active...
				doResumeSynchronization(suspendedSynchronizations);
				throw ex;
			}
		}
		else if (transaction != null) {
			// Transaction active but no synchronization active.
			Object suspendedResources = doSuspend(transaction);
			return new SuspendedResourcesHolder(suspendedResources);
		}
		else {
			// Neither transaction nor synchronization active.
			return null;
		}
	}

	/**
	 * 挂起所有的当前同步,并且取消激活当前线程的事务同步
	 * Suspend all current synchronizations and deactivate transaction
	 * synchronization for the current thread.
	 * @return the List of suspended TransactionSynchronization objects
	 */
	private List<TransactionSynchronization> doSuspendSynchronization() {
		// 获取当前线程中全部的事务同步
		List<TransactionSynchronization> suspendedSynchronizations =
				TransactionSynchronizationManager.getSynchronizations();
		// 遍历同步,使其依次挂起
		for (TransactionSynchronization synchronization : suspendedSynchronizations) {
			// 就是释放数据库连接资源
			synchronization.suspend();
		}
		// 清理同步
		TransactionSynchronizationManager.clearSynchronization();
		// 返回同步
		return suspendedSynchronizations;
	}

======================================= org.springframework.jdbc.datasource.DataSourceTransactionManager#doSuspend =======================================

	/**
	 * 执行挂起事务
	 *
	 * @param transaction the transaction object returned by {@code doGetTransaction}
	 * @return
	 */
	@Override
	protected Object doSuspend(Object transaction) {
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
		txObject.setConnectionHolder(null);
		// 释放资源
		return TransactionSynchronizationManager.unbindResource(obtainDataSource());
	}


它的逻辑是:

  1. 执行挂起同步 doSuspendSynchronization() 方法,这里边主要是从线程本地化中获取所有的事务同步 TransactionSynchronization,然后执行挂起(就是释放数据库连接资源);
  2. 然后执行 doSuspend() 方法,挂起给定的事务,返回一个当前连接资源;
  3. 清除线程本地化中当前的事务信息,有线程名称、线程只读属性、线程隔离级别、事务是否活跃标识;
  4. 创建一个挂起的资源持有器 SuspendedResourcesHolder,返回。
  5. 遇到异常执行 doResumeSynchronization() 方法,重新使用同步。

2.6.1.6 准备事务状态 prepareTransactionStatus()

接着看准备事务状态方法 org.springframework.transaction.support.AbstractPlatformTransactionManager#prepareTransactionStatus :

	/**
	 * 创建一个新的事务状态,同时初始化事务同步。
	 *
	 * Create a new TransactionStatus for the given arguments,
	 * also initializing transaction synchronization as appropriate.
	 * @see #newTransactionStatus
	 * @see #prepareTransactionStatus
	 */
	protected final DefaultTransactionStatus prepareTransactionStatus(
			TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
			boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {
		// 创建一个新的事务状态
		DefaultTransactionStatus status = newTransactionStatus(
				definition, transaction, newTransaction, newSynchronization, debug, suspendedResources);
		// 预同步事务
		prepareSynchronization(status, definition);
		return status;
	}

	/**
	 * Create a TransactionStatus instance for the given arguments.
	 */
	protected DefaultTransactionStatus newTransactionStatus(
			TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
			boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {

		boolean actualNewSynchronization = newSynchronization &&
				!TransactionSynchronizationManager.isSynchronizationActive();
		// 创建一个默认的事务状态
		return new DefaultTransactionStatus(
				transaction, newTransaction, actualNewSynchronization,
				definition.isReadOnly(), debug, suspendedResources);
	}

	/**
	 * Initialize transaction synchronization as appropriate.
	 */
	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();
		}
	}

逻辑:

  1. 执行 newTransactionStatus() 方法,创建一个事务状态 DefaultTransactionStatus 对象;
  2. 执行 prepareSynchronization() 方法,准备同步。
    1. 判断事务状态如果是新的同步,则执行以下逻辑;
    2. 设置线程本地化的实际事务活跃;
    3. 设置线程本地化的当前事务隔离级别;
    4. 设置线程本地化的当前事务是否为只读标识;
    5. 设置当前事务的名称;
    6. 初始化线程本地化同步集合。

2.6.1.7 事务状态 DefaultTransactionStatus

我们看下 DefaultTransactionStatus 对象的类图:

DefaultTransactionStatus

这个类有持有了一些事务的属性,表示当前事务的一个状态。

2.6.1.8 开启一个新事物 startTransaction()

开始看开启新事物方法 org.springframework.transaction.support.AbstractPlatformTransactionManager#startTransaction :

	/**
	 * 开启一个新的事务
	 *
	 * Start a new transaction.
	 */
	private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,
			boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {

		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
		// 创建一个事务状态
		DefaultTransactionStatus status = newTransactionStatus(
				definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
		// 开启事务
		doBegin(transaction, definition);
		// 准备同步事务
		prepareSynchronization(status, definition);
		return status;
	}

================================ org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin ================================
	/**
	 * 开启一个新的事务
	 *
	 * @param transaction the transaction object returned by {@code doGetTransaction}
	 * @param definition  a TransactionDefinition instance, describing propagation
	 *                    behavior, isolation level, read-only flag, timeout, and transaction name
	 */
	@Override
	protected void doBegin(Object transaction, TransactionDefinition definition) {
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
		Connection con = null;

		try {
			// 判断是否有连接持有器
			if (!txObject.hasConnectionHolder() ||
					txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
				// 获取一个新的连接
				Connection newCon = obtainDataSource().getConnection();
				if (logger.isDebugEnabled()) {
					logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
				}
				// 创建一个新的连接持有器,设置到事务对象中
				txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
			}

			// 设置连接持有器的事务同步属性
			txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
			// 获取连接对象
			con = txObject.getConnectionHolder().getConnection();

			// 预设值连接属性,返回隔离级别
			Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
			// 为事务对象设置隔离级别
			txObject.setPreviousIsolationLevel(previousIsolationLevel);
			// 设置只读属性
			txObject.setReadOnly(definition.isReadOnly());

			// 获取自定提交的属性,设置为 false
			// 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);
			// 设置事务对象的连接持有器的活跃属性
			txObject.getConnectionHolder().setTransactionActive(true);

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

			// 绑定一个资源
			// Bind the connection holder to the thread.
			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);
		}
	}


它的逻辑:

  1. 执行 newTransactionStatus() 方法,创建一个事务状态 DefaultTransactionStatus 对象;
  2. 执行 doBegin() 方法,开启事务;
    1. 判断事务对象 DataSourceTransactionObject 是否有连接持有器;
    2. 如果没有,创建一个新的连接 Connection、连接持有器 ConnectionHolder,并设置到事务对象中;
    3. 设置连接持有器的同步标识;
    4. 获取连接,为事务准备连接,
    5. 设置事务对象只读标识属性、隔离级别属性;
    6. 关闭连接的自动提交;
    7. 准备事务连接;
    8. 设置连接持有器的事务激活标识为 true;
    9. 设置事务对象的超时时间;
    10. 持有器是新的话,就绑定一个连接资源,到线程本地化中。
    11. 遇到异常,持有器是新的话,就释放资源,清空事务对象的连接持有器。
  3. 执行 prepareSynchronization() 方法,准备同步。

2.6.1.9 准备事务信息 prepareTransactionInfo()

获取了一个事务状态之后,接着到了准备事务信息方法了,org.springframework.transaction.interceptor.TransactionAspectSupport#prepareTransactionInfo:

	/**
	 * 准备一个事务信息。
	 *
	 * Prepare a TransactionInfo for the given attribute and status object.
	 * @param txAttr the TransactionAttribute (may be {@code null})
	 * @param joinpointIdentification the fully qualified method name
	 * (used for monitoring and logging purposes)
	 * @param status the TransactionStatus for the current transaction
	 * @return the prepared TransactionInfo object
	 */
	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;
	}

逻辑:

  1. 创建一个事务信息 TransactionInfo 对象;
  2. 设置事务信息的事务状态属性;
  3. 把事务信息绑定到绑定线程,保存旧的事务信息,把当前事务信息绑定到线程本地化中;
  4. 返回事务信息。

我们看下这个 TransactionInfo 类信息:

TransactionInfo

它持有一个事务状态、事务管理器、事务属性、方法切点。

2.6.2 处理异常 completeTransactionAfterThrowing()

在执行器执行过程中遇到异常时,会执行 org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowing 方法:

	/**
	 * Handle a throwable, completing the transaction.
	 * We may commit or roll back, depending on the configuration.
	 * @param txInfo information about the current transaction
	 * @param ex throwable encountered
	 */
	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 {
					// 进行回滚
					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 {
				// 我们不会回滚这个异常。
				// 如果 TransactionStatus.isRollbackOnly() 是 true,则任然回滚
				// 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;
				}
			}
		}
	}

逻辑为:

  1. 判断是否对该异常进行回滚;
  2. 如果需要,则进行回滚;
  3. 如果不需要则执行提交事务。

2.6.3 清理事务信息 cleanupTransactionInfo()

当目标方法都处理完毕之后,不论有没有异常抛出,都进行清除事务信息 org.springframework.transaction.interceptor.TransactionAspectSupport#cleanupTransactionInfo:

	/**
	 * Reset the TransactionInfo ThreadLocal.
	 * <p>Call this in all cases: exception or normal return!
	 * @param txInfo information about the current transaction (may be {@code null})
	 */
	protected void cleanupTransactionInfo(@Nullable TransactionInfo txInfo) {
		if (txInfo != null) {
			// 恢复线程本地化状态
			txInfo.restoreThreadLocalStatus();
		}
	}

		private void restoreThreadLocalStatus() {
			// Use stack to restore old transaction TransactionInfo.
			// Will be null if none was set.
			// 还原上一个事务信息
			transactionInfoHolder.set(this.oldTransactionInfo);
		}

主要是还原上一个事务信息到线程本地中。

2.6.4 提交事务 commitTransactionAfterReturning()

最后,当方法执行完毕,没有异常的情况下,会执行提交事务操作 org.springframework.transaction.interceptor.TransactionAspectSupport#commitTransactionAfterReturning:

	/**
	 * Execute after successful completion of call, but not after an exception was handled.
	 * Do nothing if we didn't create a transaction.
	 * @param txInfo information about the current transaction
	 */
	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());
		}
	}


======================== org.springframework.transaction.support.AbstractPlatformTransactionManager#commit ====================
	/**
	 * This implementation of commit handles participating in existing
	 * transactions and programmatic rollback requests.
	 * Delegates to {@code isRollbackOnly}, {@code doCommit}
	 * and {@code rollback}.
	 * @see org.springframework.transaction.TransactionStatus#isRollbackOnly()
	 * @see #doCommit
	 * @see #rollback
	 */
	@Override
	public final void commit(TransactionStatus status) throws TransactionException {
		if (status.isCompleted()) {
			throw new IllegalTransactionStateException(
					"Transaction is already completed - do not call commit or rollback more than once per transaction");
		}

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

	/**
	 * 处理实际的回滚。已经检查了完成标记。
	 *
	 * Process an actual rollback.
	 * The completed flag has already been checked.
	 * @param status object representing the transaction
	 * @throws TransactionException in case of rollback failure
	 */
	private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
		try {
			boolean unexpectedRollback = unexpected;

			try {
				// 触发前置完成事件
				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;
			}
			// 触发完成之后事件
			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);
		}
	}

	/**
	 * Process an actual commit.
	 * Rollback-only flags have already been checked and applied.
	 * @param status object representing the transaction
	 * @throws TransactionException in case of commit failure
	 */
	private void processCommit(DefaultTransactionStatus status) throws TransactionException {
		try {
			boolean beforeCompletionInvoked = false;

			try {
				boolean unexpectedRollback = false;
				prepareForCommit(status);
				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();
				}

				// 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) {
					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 {
				triggerAfterCommit(status);
			}
			finally {
				triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
			}

		}
		finally {
			cleanupAfterCompletion(status);
		}
	}

这里的逻辑稍微复杂点:

  1. 判断事务状态是否是仅回滚的,如果是那就执行 processRollback() 方法,执行回滚;
    1. 执行 triggerBeforeCompletion() 方法,触发前置完成事件,底层调用事务同步 TransactionSynchronization 的 beforeCompletion() 方法;
    2. 判断一下条件,执行各自的逻辑
      1. 如果有保存点,那就执行事务状态的 rollbackToHeldSavepoint() 方法,回滚到保存点;
      2. 如果是新事物,执行 doRollback() 方法,进行回滚;
      3. 都不是,则执行 doSetRollbackOnly() 方法,给事务对象设置回滚标识,让上层事务进行回滚。
    3. 执行 triggerAfterCompletion() 方法,执行完成操作,底层调用事务同步 TransactionSynchronization 的 afterCompletion() 方法;
    4. 最后执行 cleanupAfterCompletion() 方法,进行清除操作。
      1. 新的同步则执行清理线程本地化操作;
      2. 新的事务,则执行释放连接操作;
      3. 如果有挂起的资源,恢复挂起的资源。
  2. 不是的话,就执行 processCommit() 方法,进行提交。
    1. 执行 triggerBeforeCommit() 方法,执行提交前的操作,底层调用事务同步 TransactionSynchronization 的 beforeCommit() 方法;
    2. 执行 triggerBeforeCompletion() 方法,执行完成前的操作,底层调用事务同步 TransactionSynchronization 的 beforeCompletion() 方法;
    3. 判断一下条件,执行各自的逻辑;
      1. 如果有保存点,则执行事务状态的 releaseHeldSavepoint() 方法,释放保存点;
      2. 如果是新的事务,则执行 doCommit() 方法,进行提交;
      3. 全局回滚时提前失败检查。
    4. 执行 triggerAfterCompletion() 方法,执行完成之后的操作,底层调用事务同步 TransactionSynchronization 的 afterCompletion() 方法;
    5. 遇到异常时,执行 doRollbackOnCommitException() 方法,进行回滚;
    6. 没有遇到异常,执行 triggerAfterCommit() 方法,执行完成之后的操作;
    7. 最后执行 cleanupAfterCompletion() 方法,进行清理操作。
      1. 新的同步则执行清理线程本地化操作;
      2. 新的事务,则执行释放连接操作;
      3. 如果有挂起的资源,恢复挂起的资源。

总结

上面就是 spring tx 模板的核心流程了。回顾下:

  1. 通过 @EnableTransactionManagement 注解,导入了 TransactionManagementConfigurationSelector 类;
  2. TransactionManagementConfigurationSelector 类,它导入了AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration 类;
  3. AutoProxyRegistrar 类负责注册一个 InfrastructureAdvisorAutoProxyCreator 类,它是一个创建代理对象的后置处理器;
  4. ProxyTransactionManagementConfiguration 类是创建了负责处理事务的增强器 BeanFactoryTransactionAttributeSourceAdvisor、还有处理事务属性的事务属性源 AnnotationTransactionAttributeSource、以及对目标方法进行事务处理拦截的事务拦截器 TransactionInterceptor,这三个 bean;
  5. 其中在调用目标方法时,通过事务拦截器 TransactionInterceptor 对目标方法进行拦截;
  6. 拦截有创建以及初始化事务相关信息(事务状态、事务对象、事务同步等信息)、执行目标方法、提交或者回滚事务、清理事务等流程。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章