Spring事务源码解析

落爺英雄遲暮 提交于 2020-03-15 19:04:38

前言

    Spring-tx支持了诸多持久化框架的事务操作,例如:JPA、Hibernate以及mybatis、spring-jdbc等。这篇主要对  DataSourceTransactioManager (支持spring-jdbc和mybatis) 进行分析。包含注解开启事务、事务注解@Transactional的原理等。

 

简单介绍

     spring-tx将事务管理抽象成3个主要的组件:

  • PlatformTransactionManager:平台事务管理器,平行的还有个 ReactiveTransactionManager,都继承自 TransactionManager,先不做分析。子类如下:
    • DataSourceTransactioManager 、 HibernateTransactioManager 、 JPATransactioManager :对主流持久化框架的支持。
    • JtaTransactioManager :分布式事务支持。
  • TransactionDefinition:事务定义信息,例如隔离级别、传播途径、事务超时时间、只读等。
  • TransactionStatus:事务具体运行状态
事务的隔离级别
隔离级别 含义
ISOLATION_DEFAULT 使用后端数据库默认使用的隔离级别(Spring中默认选项)
ISOLATION_READ_UNCOMMITTED
(读未提交)
可能出现所有并发问题,效率最高,但不可用!
ISOLATION_READ_COMMITTED
(读已提交)
防止了脏读
但没有防止不可重复读以及幻读——oracle默认支持
ISOLATION_EPEATABLE_READ
(可重复读)
防止了脏读、不可重复读
但没有防止幻读--mysql默认支持
ISOLATION_SERIALIZABLE
(串行化)
即非并发的,所以不会出现任何并发问题。
易出现死锁,效率太低!不可用!
事务的传播行为
类型 说明 举例
PROPAGATION_REQUIRED
支持当前事务
如果不存,就建一个(默认的)
A,B,如果A有事务,则B使用A事务。如果A没有事务,则B开启一个新的事务。(A,B在同一个事务中)
PROPAGATION_SUPPORTS
支持当前事务
如果不存在,就不使用事务
A,B,如果A有事务,则B就使用A的事务。如果A没有事务,则B就不使用事务
PROPAGATION_MANDATORY
支持当前事务
如果不存在,抛出异常
A,B,如果A有事务,则B就使用A的事务。如果A没有事务,则B抛出异常
PROPAGATION_REQUIRES_NEW
如果有事务存在
挂起当前事务,创建一个新的事务
A,B,如果A有事务,B将A的事务挂起,并重新创建一个事务(A,B不在一个事务中,两个事务互不影响)
PROPAGATION_NOT_SUPPORTED
以非事务方式运行
如果有事务存在,挂起当前事务
A,B,非事务方式运行,A有事务就挂起事务
PROPAGATION_NEVER
以非事务方式运行
如果有事务存在,抛出异常
总是以非事务运行
PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行
基于SavePonit技术。(保存点)
A,B,A有事务,A执行之后,将A事务执行之后的内容保存到SavePonit。B事务有异常的情况,用户需要自己设置事务是提交还是回滚到保存点

 

 

使用

  • 注意:默认情况下Spring中的事务处理只对RuntimeException进行回滚。

编程式

<!--配置事务管理器-->
<bean id="txManager"
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
</bean>

<!--配置事务管理的模版-->
<bean id="transactionTemplate"
	class="org.springframework.transaction.support.TransactionTemplate">
	<property name="transactionManager" ref="txManager" />
</bean>
@Service
public class UserService {
    
    @Autowired
    private TransactionTemplate transactionTemplate;
    
    
    public void transfer(final String out, final String in, final Double money){
        transactionTemplate.execute(new TransactionCallbackWithoutResult(){
           @Override
           protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
               ....
               // 发生异常会进行事务回滚
               int i = 1/0;
               ...
           }
        });
    }
    
}

声明式

  • 单个类配置,transactionAttributes可配置项有:PROPAGATION:事务传播行为; ISOLATION:事务隔离级别; readOnly:只读; -Exception:发生哪些异常事务回滚;+Exception:发生哪些异常事务不回滚。用逗号分隔。
    • 这个就不具体介绍了,用的也不多。
<bean id="txManager"
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
</bean>

<bean id="userServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="target" ref="userService" />
    <property name="transactionManager" ref="txManager" />
    <!--配置方法的传播行为、隔离级别等,用逗号隔开-->
    <property name="transactionAttributes">
        <props>
            <prop key="insert*">PROPAGATION_REQUIRED</prop>
            <prop key="transfer">PROPAGATION_REQUIRED</prop>
        </props>
    </property>
</bean>
  • 切面配置,通过配置切点及增强Advisor,并进行关联,借助aop匹配,支持满足条件的多个方法被事务增强。

<bean id="txManager"
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
</bean>

<!--使用spring提供的tx:advice管理事务-->
<tx:advice id="txAdvice" transaction-manger="txManager">
    <tx:attributes>
        <!--
            propagation:事务传播行为
            isolation:事务隔离级别
            read-only:只读
            rollback-for:发生哪些异常回滚事务
            no-rollback-for:发生哪些异常不回滚事务
            time-out:过期
        -->
        <tx:method name="transfer" propagation="REQUIRED" />
    </tx:attributes>
</tx:advice>

<!--配置切面-->
<aop:config>
    <!--指定切面-->
    <aop:pointcut id="pointcut1" expression="execution(* menghao.service.*.*(..))" />
    <!--将切面与增强关联-->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1" />
</aop:config>
  • 注解事务:开启后使用@Transactional注解标识方法即可,常用。@EnableTransactionManagement开启事务其实跟下面配置起到了等同的效果。
<bean id="txManager"
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
</bean>

<!--支持注解事务-->
<tx:annotation-driven transaction-manager="txManager" />

 

源码

    看过了怎样使用,接下来就开始分析事务的实现原理,从 @EnableTransactionManagement开始入手。首先来看下该注解的定义

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
    
    /**
     * false:优先JDK动态代理,代理类无接口使用ciglib;
     * true:强制Ciglib代理
     */
    boolean proxyTargetClass() default false;
    
    /**
     * 基于JDK代理的增强 还是 AspectJ增强
     */
	AdviceMode mode() default AdviceMode.PROXY;

	/**
	 * 指示在切点应用多个切面增强时,事务切面执行顺序
	 */
	int order() default Ordered.LOWEST_PRECEDENCE;

}

    对应这个事务开启的注解,有一个对应的selector进行bean的注册。这里便是 TransactionManagementConfigurationSelector。

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

	@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() {
	    // 看是否有必要支持JTA规范
		return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
				TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
				TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
	}

}

    AutoProxyRegistrar 就不展开分析了,它的作用就是根据 @EnableTransactionManagement设置的 mode如果为PROXY,则注册InfrastructureAdvisorAutoProxyCreator类来对满足条件的对象自动创建代理。主要分析下PROXY模式:

PROXY模式

    承接上面的,proxy模式除了引入了 AutoProxyRegistrar,另一个就是 ProxyTransactionManagementConfiguration。这个类作为一个配置类,会引入4个主要的bean:

  • BeanFactoryTransactionAttributeSourceAdvisor:事务增强的 Advisor,内部包含了 TransactionAttributeSource实例以及的定义了具体的切点。
  • AnnotationTransactionAttributeSource:对 @Transactional 注解解析的支持。
    • 会被设置到 BeanFactoryTransactionAttributeSourceAdvisor。
  • TransactionInterceptor:具体切面的执行者,可以看作是涵盖了事务的开启,判断事务需要提交还是回滚的主要逻辑。
    • 会被设置到 BeanFactoryTransactionAttributeSourceAdvisor。
  • TransactionalEventListenerFactory:这个类是在 ProxyTransactionManagementConfiguration父类 AbstractTransactionManagementConfiguration中引入的,为了支持  @TransactionalEventListener 的识别和创建。
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
    // AnnotationTransactionAttributeSource
	@Nullable
	private TransactionAttributeSource transactionAttributeSource;

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

	public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
		this.transactionAttributeSource = transactionAttributeSource;
	}

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

    从切点的定义来看,使用匿名内部类的实现方式,将 Advisor中的 TransactionAttributeSource(这里实现就是 AnnotationTransactionAttributeSource)给到pointcut,接下来看下具体的切点定义:

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

	protected TransactionAttributeSourcePointcut() {
        // 类级别的过滤,使用内部类 TransactionAttributeSourceClassFilter 
		setClassFilter(new TransactionAttributeSourceClassFilter());
	}

	@Override
	public boolean matches(Method method, Class<?> targetClass) {
		// 这里获取的是子类(匿名内部类)实现的 getTransactionAttributeSource的返回,也就是 AnnotationTransactionAttributeSource
		TransactionAttributeSource tas = getTransactionAttributeSource();
		return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
	}

	private class TransactionAttributeSourceClassFilter implements ClassFilter {

		@Override
		public boolean matches(Class<?> clazz) {
            // 特定的类不匹配
			if (TransactionalProxy.class.isAssignableFrom(clazz) ||
					PlatformTransactionManager.class.isAssignableFrom(clazz) ||
					PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
				return false;
			}
            // 获取事务元数据(比如 @Transactional)不为空,说明匹配成功
			TransactionAttributeSource tas = getTransactionAttributeSource();
			return (tas == null || tas.isCandidateClass(clazz));
		}
	}
}

    这里 AnnotationTransactionAttributeSource的源码也不展开分析了,它主要提供了事务注解的识别和解析动作,除了支持 spring的@Transactional,还支持JTA的 javax.transaction.Transactional ,EJB的 javax.ejb.TransactionAttribute。以及对这些注解的解析动作(getTransactionAttribute方法),以spring的@Transactional识别的条件举例:方法必须是publish、且方法或类上被@Transactional标识

    一旦切点匹配上了,接下来就要是切面事务增强逻辑的调用了(org.aopalliance.intercept.MethodInterceptor#invoke)。

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {

	@Override
	@Nullable
	public Object invoke(MethodInvocation invocation) throws Throwable {
		// 获取目标类
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
        // 调用父类方法 invokeWithinTransaction
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}
}

主要动作  

  调用父类的 invokeWithinTransaction方法,这里我们只分析 PlatformTransactionManager 类型的处理。主要分为几个主要步骤:

  • 封装事务信息与当前线程绑定,并记录上一个事务信息。
  • 切点方法异常处理/正常返回处理。
  • 将事务信息与当前线程解绑,并把方法执行前上一个的事务信息与当前线程绑定。
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {

	@Nullable
	protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {
		// 获取事务元数据,为空说明所切到的方法没有识别到事务元数据(比如@Transactional)
		TransactionAttributeSource tas = getTransactionAttributeSource();
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
		// 通过元数据决定事务管理器,比如 org.springframework.transaction.annotation.Transactional.transactionManager可以指定
		// 默认全局只能定义一个 TransactionManager
		final TransactionManager tm = determineTransactionManager(txAttr);
        
        // 省略 ReactiveTransactionManager类型的处理

		PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
        // 定义切点方法的唯一身份标识,相当于起个string类型的名字用于区分
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

		if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
			// 封装事务信息并与当前线程绑定
			TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

			Object retVal;
			try {
				// 回调切点方法
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				// 异常处理
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
				// 事务信息与当前事务解绑
				cleanupTransactionInfo(txInfo);
			}

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

        // 省略 CallbackPreferringPlatformTransactionManager类型处理
	
	}
}

封装事务信息

    委托给 org.springframework.transaction.PlatformTransactionManager#getTransaction

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

		// 如果没有名称,使用之前创建的方法标识作为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) {
			    // 根据传播行为返回事务 or 新建事务
				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);
	}

异常处理

    委托给 org.springframework.transaction.PlatformTransactionManager#rollback

	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 {
				    // PlatformTransactionManager.rollback
					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 {
				// 非回滚异常进行如下处理
				// 如果设置了 RollbackOnly(),还是会回滚。否则提交
				try {
				    // PlatformTransactionManager.commit
					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;
				}
			}
		}
	}

正常返回处理

    委托给 org.springframework.transaction.PlatformTransactionManager#commit

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

从上面3个主要逻辑来看,主要的工作被封装在了 org.springframework.transaction.PlatformTransactionManager实现类中。接下来分析开头提到了  DataSourceTransactionManager实现,介绍它之前,先来看下他的抽象父类 org.springframework.transaction.support.AbstractPlatformTransactionManager,实现了逻辑的主体,子类只需要在需要定制的地方进行扩展即可。

AbstractPlatformTransactionManager

  • getTransaction

    可大体分为当前有事务和无事务两条处理线,当前方法主要是无事务的处理逻辑,有事务的处理逻辑被封装在 handleExistingTransaction

	@Override
	public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException {

		// 如果为空则使用默认实例:即传播途径默认 PROPAGATION_REQUIRED;隔离级别默认 ISOLATION_DEFAULT;超时时间默认 -1等
		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);
		}
         /************** 以下逻辑为:当前无事务的处理逻辑 ***********/
		// 检测设置的事务超时时间是否合理
		if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
			throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
		}

		/**
		 * 传播行为设置为以下的处理
		 *  - PROPAGATION_MANDATORY:当前事务不存在,抛出异常
		 */
		if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		/**
		 * 传播行为设置为以为的处理
		 *  - PROPAGATION_REQUIRED
		 *  - PROPAGATION_REQUIRES_NEW
		 *  - PROPAGATION_NESTED
		 */
		else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
				def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
			// 返回当前事务状态对象,连接等信息封装成 SuspendedResources
			SuspendedResourcesHolder suspendedResources = suspend(null);
			if (debugEnabled) {
				logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
			}
			try {
				// 根据参数创建新的事务状态实例,子类扩展开始事务(doBegin)
				return startTransaction(def, transaction, debugEnabled, suspendedResources);
			}
			catch (RuntimeException | Error ex) {
				resume(null, suspendedResources);
				throw ex;
			}
		}
		/**
		 * 开头已经判断如果有事务,执行另一套分支,所以到这里就是无事务,剩下的3个也就没什么区分了:
		 * - PROPAFATION_SUPPORTS:支持当前事务;如果不存在,就不使用事务
		 * - PROPAFATION_NOT_SUPPORTED:以非事务方式运行, 如果有事务存在,挂起当前事务
		 * - PROPAFATION_NEVER:以非事务方式运行,如果有事务存在,抛出异常
		 */
		else {
			if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
				logger.warn("Custom isolation level specified but no actual transaction initiated; " +
						"isolation level will effectively be ignored: " + def);
			}
			// 返回事务状态
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
		}
	}

​​​​​    当前执行前已经存在事务的处理:

	private TransactionStatus handleExistingTransaction(
			TransactionDefinition definition, Object transaction, boolean debugEnabled)
			throws TransactionException {
		// PROPAGATION_NEVER:有事务抛出异常
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
			throw new IllegalTransactionStateException(
					"Existing transaction found for transaction marked with propagation 'never'");
		}
		// PROPAGATION_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);
		}
		// PROPAGATION_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;
			}
		}
		 // PROPAGATION_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.
				// 通过 SavepointManager创建 savepoints
				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.
				// 不支持savepoints机制,则通过嵌套的 begin和 commit/rollback调用实现
				return startTransaction(definition, transaction, debugEnabled, null);
			}
		}

		/**
		 * 能进入当前方法的前提就是有事务,所以剩下的两种传播类型可视为一种,即仍使用当前事务:
		 * PROPAGATION_SUPPORTS:支持当前事务,如果不存在,就不使用事务
		 * PROPAGATION_REQUIRED:支持当前事务,如果不存,就建一个(默认的)
		 */
		if (debugEnabled) {
			logger.debug("Participating in existing transaction");
		}
		if (isValidateExistingTransaction()) {
			if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
				Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
				if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
					Constants isoConstants = DefaultTransactionDefinition.constants;
					throw new IllegalTransactionStateException("Participating transaction with definition [" +
							definition + "] specifies isolation level which is incompatible with existing transaction: " +
							(currentIsolationLevel != null ?
									isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
									"(unknown)"));
				}
			}
			if (!definition.isReadOnly()) {
				if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
					throw new IllegalTransactionStateException("Participating transaction with definition [" +
							definition + "] is not marked as read-only but existing transaction is");
				}
			}
		}
		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
		return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
	}
  • commit

	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;
		// 是否设置了 rollback-only,如果设置了则回滚
		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);
	}
  • rollback

	@Override
	public final void rollback(TransactionStatus status) throws TransactionException {
		// 如果事务已完成则抛出异常
		if (status.isCompleted()) {
			throw new IllegalTransactionStateException(
					"Transaction is already completed - do not call commit or rollback more than once per transaction");
		}

		DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
		// 执行回滚
		processRollback(defStatus, false);
	}

针对以上出现的需要子类定制的方法,这里做一些逻辑的简述,全部以 DataSourceTransactionManager实现来简述,就不贴源码了:

  • startTransaction:会调用doBegin,由子类扩展。
    • 如果发现当前事务没有持有JDBC连接(即java.sql.Connection),则调用 DataSource进行创建,否则复用 JDBC连接,
    • 获取其隔离级别,并强制设置为手动提交(即autoCommit为false)。
    • 设置事务状态为激活(即transactionActive为true)
    • 设置事务超时时间(非TIMEOUT_DEFAULT,即-1时才会设置)
    • 如果是新创建的JDBC连接,还会同当前线程进行绑定。
  • processCommit:
    • 如果有 savepoint,则清空
    • 如果当前的事务是新创建的,而不是复用之前已存在的事务,则调用doCommit进行提交
    • 最后做一些清理重置工作
  • processRollback:
    • 如果有 savepoint,则回滚之该点。
    • 如果当前的事务是新创建的,而不是复用之前已存在的事务,则调用doRollback进行回滚
    • 最后同样是一些清理重置工作

 

总结

    目前已经将Spring事务原理的大体逻辑分析完毕,个别细节点没有展开,如果后期有用到,再继续追加吧。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!