spring源码(四)事务

spring事务相对于编程式的事务,基本用的都是声明式事务,这篇文章讲的也就是声明式事务是如何实现的。

想要开启声明式事务,首先需要使用@EnableTransactionManagement注解,所以分析spring事务的源码就从分析这个注解开始。

点开注解可以看到很熟悉的@Import导入,导入的类是TransactionManagementConfigurationSelector,这个从名字基本就可以看出是一个ImportSelector的导入类。

TransactionManagementConfigurationSelector的继承关系比较简单,继承于AdviceModeImportSelector,再然后就是ImportSelector

代码比较简单,就是判断一下代理的类型,然后决定返回什么类型,默认是Proxy代理,所以返回的是ProxyTransactionManagementConfiguration类型,这里要申明的一点Proxy类型不是指的jdk的proxy代理,而是spring aop的代理,因为另外一个类型是ASPECTJ,这个是对第三方ASPECTJ代理的支持,这里如果不明白可以看之前AOP的博客。

ProxyTransactionManagementConfiguration类型被返回后,最后会放入spring容器中,分析一下ProxyTransactionManagementConfiguration的代码。

代码不多,直接全放上来

/**
 * {@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)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

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

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

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

}

先看transactionAdvisor方法,参数是TransactionAttributeSource 和TransactionInterceptor ,很明显依赖于下面两个方法,下面两个方法生成Bean之后在这里注入,重点就是transactionAdvisor方法的返回BeanFactoryTransactionAttributeSourceAdvisor ,看一看结构图,继承于Advisor,还记得在之前Aop博客中提到过,在一个findCandidateAdvisors方法中,会找出容器中继承了Advisor接口的类

而Advisor是Pointcut以及Advice的集合,BeanFactoryTransactionAttributeSourceAdvisor的Advice就是传入的TransactionInterceptor,代码在上面。而Pointcut内部默认

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

先看类的过滤,getTransactionAttributeSource方法是抽象方法,实现在上面那段代码,获取到的是一个TransactionAttributeSource ,而TransactionAttributeSource在之前说过,是@Bean加入spring容器,方法参数注入进来的

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

		@Override
		public boolean matches(Class<?> clazz) {
			if (TransactionalProxy.class.isAssignableFrom(clazz) ||
					TransactionManager.class.isAssignableFrom(clazz) ||
					PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
				return false;
			}
			TransactionAttributeSource tas = getTransactionAttributeSource();
			return (tas == null || tas.isCandidateClass(clazz));
		}
	}

此时TransactionAnnotationParser一般只有SpringTransactionAnnotationParser,最终的方法就是看有没有@Transaction注解

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

然后是方法级别的过滤,方法过滤就是分别看方法以及方法的类上能不能获取到TransactionAttribute,可以的话就返回true,TransactionAttribute就是@Transaction注解的属性集合。

	// We need to work it out.
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
		RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();

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

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

		return rbta;
	}

都返回true之后,就会进行代理,接下来就看代理的代码逻辑,进入到TransactionInterceptor中,分析invoke方法

调用的方法是invokeWithinTransaction

首先会获取目标的TransactionAttribute,并根据这个来选取TransactionManager 

// If the transaction attribute is null, the method is non-transactional.
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
final TransactionManager tm = determineTransactionManager(txAttr);

determineTransactionManager方法的逻辑就是先判断@Transaction注解的value属性是不是有值,就的话就用这个从BeanFactory中获取到这个TransactionManager,否则用当前的transactionManagerBeanName这个属性从容器中获取,这里默认没有设置这个属性,如果以上都不满足,那就会从容器中通过TransactionManager类型找出一个默认的TransactionManager

/**
	 * Determine the specific transaction manager to use for the given transaction.
	 */
	@Nullable
	protected TransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
		// Do not attempt to lookup tx manager if no tx attributes are set
		if (txAttr == null || this.beanFactory == null) {
			return getTransactionManager();
		}

		String qualifier = txAttr.getQualifier();
		if (StringUtils.hasText(qualifier)) {
			return determineQualifiedTransactionManager(this.beanFactory, qualifier);
		}
		else if (StringUtils.hasText(this.transactionManagerBeanName)) {
			return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
		}
		else {
			TransactionManager defaultTransactionManager = getTransactionManager();
			if (defaultTransactionManager == null) {
				defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
				if (defaultTransactionManager == null) {
					defaultTransactionManager = this.beanFactory.getBean(TransactionManager.class);
					this.transactionManagerCache.putIfAbsent(
							DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
				}
			}
			return defaultTransactionManager;
		}
	}

	private TransactionManager determineQualifiedTransactionManager(BeanFactory beanFactory, String qualifier) {
		TransactionManager txManager = this.transactionManagerCache.get(qualifier);
		if (txManager == null) {
			txManager = BeanFactoryAnnotationUtils.qualifiedBeanOfType(
					beanFactory, TransactionManager.class, qualifier);
			this.transactionManagerCache.putIfAbsent(qualifier, txManager);
		}
		return txManager;
	}

获取到当前的TransactionManager之后,先跳过ReactiveTransactionManager以及CallbackPreferringPlatformTransactionManager,先创建Treansaction

	// Standard transaction demarcation with getTransaction and commit/rollback calls.
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
if (tm != null) {
	status = tm.getTransaction(txAttr);
}

用默认的TransactionManager的话,这里getTransaction调用的是AbstractPlatformTransactionManager中的方法

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

doGetTransaction调用的是DataSourceTransactionManager的方法,这里返回的是一个DataSourceTransactionObject 

	@Override
	protected Object doGetTransaction() {
		DataSourceTransactionObject txObject = new DataSourceTransactionObject();
		txObject.setSavepointAllowed(isNestedTransactionAllowed());
		ConnectionHolder conHolder =
				(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
		txObject.setConnectionHolder(conHolder, false);
		return txObject;
	}

obtainDataSource方法返回的是当前的Datasource,接着调用getResource方法获取ConnectionHolder,方法中将Datasource计算出一个key,接着从ThreadLocal中获取Map,从map中获取对应的ConnectionHolder

/**
	 * Retrieve a resource for the given key that is bound to the current thread.
	 * @param key the key to check (usually the resource factory)
	 * @return a value bound to the current thread (usually the active
	 * resource object), or {@code null} if none
	 * @see ResourceTransactionManager#getResourceFactory()
	 */
	@Nullable
	public static Object getResource(Object key) {
		Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
		Object value = doGetResource(actualKey);
		if (value != null && logger.isTraceEnabled()) {
			logger.trace("Retrieved value [" + value + "] for key [" + actualKey + "] bound to thread [" +
					Thread.currentThread().getName() + "]");
		}
		return value;
	}
private static final ThreadLocal<Map<Object, Object>> resources =
			new NamedThreadLocal<>("Transactional resources");
	/**
	 * Actually check the value of the resource that is bound for the given key.
	 */
	@Nullable
	private static Object doGetResource(Object actualKey) {
		Map<Object, Object> map = resources.get();
		if (map == null) {
			return null;
		}
		Object value = map.get(actualKey);
		// Transparently remove ResourceHolder that was marked as void...
		if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
			map.remove(actualKey);
			// Remove entire ThreadLocal if empty...
			if (map.isEmpty()) {
				resources.remove();
			}
			value = null;
		}
		return value;
	}

最后返回,接着判断当前是否存在transaction事务,判断依据就是有没有ConnectionHolder并且是Active状态的,第一次进来肯定是没有

isExistingTransaction(transaction)
	@Override
	protected boolean isExistingTransaction(Object transaction) {
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
		return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
	}

根据当前有没有事务,会执行不同的方法,如果有事务,会调用handleExistingTransaction方法,否则当前没有事务就会往下执行,先看当前没有事务的情况

首先,如果事务传播行为Propagation是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'");
}

接着判断REQUIRED,REQUIRES_NEW和NESTED的情况,这三个分别代表着

如果存在事务,加入事务,否则新建

无论存不存在事务,都新建事务

如果存在事务,就创建嵌套事务,不存在事务,就新建事务

所以当前不存在事务的情况下,上面三种行为都是一样的,都要新建一个事务

SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
	logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
}
try {
	boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
	DefaultTransactionStatus status = newTransactionStatus(
			def, transaction, true, newSynchronization, debugEnabled, suspendedResources);
	doBegin(transaction, def);
	prepareSynchronization(status, def);
	return status;
}

先执行suspend挂起事务方法,这里应该是没有任何操作

如果当前没有ConnectionHolder,就会获取一个新的Connection连接并创建ConnectionHolder

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

接着构建Connection,设置连接和事务属性,setSynchronizedWithTransaction为true简单来说就是标识这个事务会放入到ThreadLocal中,用于同步。

txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
txObject.setReadOnly(definition.isReadOnly());
// 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);
}

最后如果是一个新的连接,就会设置到ThreadLocal中

// Bind the connection holder to the thread.
if (txObject.isNewConnectionHolder()) {
	TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
}

接着同步事务的信息,把信息放入对应的ThreadLocal中。

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

再回头看看如果当前有事务的情况

如果是NEVER,表示只能在没有事务的环境下执行,所以直接抛异常

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

如果是NOT_SUPPORTED,表示在没有事务的环境下运行,如果有事务,就挂起。

看看挂起事务的方法,suspend,传入之前创建的DataSourceTransactionObject。

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

然后调用doSuspend,这个方法在子类中实现,DataSourceTransactionManager实现如下,就是从本地线程池中删除掉Resource资源,也就是ConnectionHolder,并且返回删除的ConnectionHolder

	@Override
	protected Object doSuspend(Object transaction) {
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
		txObject.setConnectionHolder(null);
		return TransactionSynchronizationManager.unbindResource(obtainDataSource());
	}

如果是同步事务,还会删除本地线程池中的同步信息,最后创建一个SuspendedResourcesHolder返回

最后再创建DefaultTransactionStatus,传入这个挂起的事务,接着返回

如果是REQUIRES_NEW,这个表示有没有事务,都会创建一个新的事务

所以首先,同样挂起当前事务,创建DefaultTransactionStatus,和NOT_SUPPORTED不同,这里还需要新建事务,并且同步当前的事务,逻辑和之前新建事务一样,唯一不同就是传入参数当前挂起的事务之前是空的,这次是有值的。

再看NESTED,嵌套事务,这个表示子事务回滚,父事务不影响,父事务回滚,所有子事务都回滚。

如果是jdbc的事务,那么会创建一个savepoint保存点,返回DefaultTransactionStatus

如果是jta事务,那么就会直接新建一个事务

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

如果是REQUIRED和SUPPORTS,那就是根据当前事务创建一个DefaultTransactionStatus返回。

所以在getTransaction方法中,最后所有的事务传播行为最后返回的都是DefaultTransactionStatus,拿到这个DefaultTransactionStatus之后,会创建一个TransactionInfo,传入DefaultTransactionStatus,最后将TransactionInfo放入到transactionInfoHolder这个ThreadLocal中

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

事务的创建基本到此为止,接下来看当事务提交以及抛出异常后事务执行的操作

首先看异常的处理,如果是回滚的异常,那么就会回滚,否则继续提交

/**
	 * 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 {
				// 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;
				}
			}
		}
	}

而回滚之后最后会调用cleanupAfterCompletion方法,这个最后去看。

接着看事务的提交commitTransactionAfterReturning

txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());

调用的是AbstractPlatformTransactionManager的方法,最后会调用processCommit

prepareForCommit(status);
triggerBeforeCommit(status);
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;

先是prepareForCommit,这个由子类实现,默认空方法

接着triggerBeforeCommit方法,获取了当前线程所有的同步事务,逐个调用beforeCommit方法,获取当前的sqlSession,进行commit,而在sqlSession中,transaction用的是SpringManagedTransaction,会判断是否是spring的事务,所以实际上这里不会调用真正的commit

/**
	 * Trigger {@code beforeCommit} callbacks on all currently registered synchronizations.
	 * @param readOnly whether the transaction is defined as read-only transaction
	 * @throws RuntimeException if thrown by a {@code beforeCommit} callback
	 * @see TransactionSynchronization#beforeCommit(boolean)
	 */
	public static void triggerBeforeCommit(boolean readOnly) {
		for (TransactionSynchronization synchronization : TransactionSynchronizationManager.getSynchronizations()) {
			synchronization.beforeCommit(readOnly);
		}
	}
 this.holder.getSqlSession().commit()
  private void openConnection() throws SQLException {
    this.connection = DataSourceUtils.getConnection(this.dataSource);
    this.autoCommit = this.connection.getAutoCommit();
    this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource);

    LOGGER.debug(() -> "JDBC Connection [" + this.connection + "] will"
        + (this.isConnectionTransactional ? " " : " not ") + "be managed by Spring");
  }

接着调用triggerBeforeCompletion方法

首先清除了LocalThread中的事务资源Resource,接着调用了SqlSession的close方法,和之前一样,这都是为了执行SqlSession中commit以及close方法中除了提交事务以外的操作,例如缓存的处理

  // Issue #18 Close SqlSession and deregister it now
      // because afterCompletion may be called from a different thread
      if (!this.holder.isOpen()) {
        LOGGER
            .debug(() -> "Transaction synchronization deregistering SqlSession [" + this.holder.getSqlSession() + "]");
        TransactionSynchronizationManager.unbindResource(sessionFactory);
        this.holderActive = false;
        LOGGER.debug(() -> "Transaction synchronization closing SqlSession [" + this.holder.getSqlSession() + "]");
        this.holder.getSqlSession().close();
      }

嵌套事务会释放当前的保存点

if (status.hasSavepoint()) {
	if (status.isDebug()) {
		logger.debug("Releasing transaction savepoint");
	}
	unexpectedRollback = status.isGlobalRollbackOnly();
	status.releaseHeldSavepoint();
}

最后进行事务的提交

     doCommit(status);

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

事务提交完成之后调用triggerAfterCommit以及triggerAfterCompletion方法做一些后置操作

最后调用cleanupAfterCompletion方法,清除当前线程LocalThread中的数据,释放连接,最后如果当前有挂起的事务,那么会恢复

/**
	 * Resume the given transaction. Delegates to the {@code doResume}
	 * template method first, then resuming transaction synchronization.
	 * @param transaction the current transaction object
	 * @param resourcesHolder the object that holds suspended resources,
	 * as returned by {@code suspend} (or {@code null} to just
	 * resume synchronizations, if any)
	 * @see #doResume
	 * @see #suspend
	 */
	protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)
			throws TransactionException {

		if (resourcesHolder != null) {
			Object suspendedResources = resourcesHolder.suspendedResources;
			if (suspendedResources != null) {
				doResume(transaction, suspendedResources);
			}
			List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;
			if (suspendedSynchronizations != null) {
				TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);
				TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);
				TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);
				TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);
				doResumeSynchronization(suspendedSynchronizations);
			}
		}
	}

而恢复的事务会在下一个代理返回被提交。事务流程执行完毕。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值