Spring事务源码(二)

Spring事务源码(二)

本文介绍Spring事务如果在当前存在事务是如何处理的



前言

在AbstractPlatformTransactionManager#getTransaction这个方法中取出事务对象transaction ,其内部封装了ConnectionHolder对象,这个对象是从线程变量中取出来的,如果取到了且判断是isTransactionActive的则说明当前线程已经开启过事务了,那么就会走handleExistingTransaction方法,按有事务的方式执行

@Override
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
	// 获取事务对象
	Object transaction = doGetTransaction();

	// Cache debug flag to avoid repeated checks.
	boolean debugEnabled = logger.isDebugEnabled();

	if (definition == null) {
		// Use defaults if no transaction definition given.
		definition = new DefaultTransactionDefinition();
	}
	// 判断当前线程是否有事务,如有则按执行handleExistingTransaction方法
	if (isExistingTransaction(transaction)) {
		// Existing transaction found -> check propagation behavior to find out how to behave.
		return handleExistingTransaction(definition, transaction, debugEnabled);
	}
	// 以下省略

一、handleExistingTransaction

如果当前线程有事务存在,则调用此方法返回TransactionStatus 对象

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) {
		Object suspendedResources = suspend(transaction);
		boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
		return prepareTransactionStatus(
				definition, null, false, newSynchronization, debugEnabled, suspendedResources);
	}
	// 如果传播行为是PROPAGATION_NOT_SUPPORTED,则挂起当前线程,调用doBegin重新获取事务
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
		SuspendedResourcesHolder suspendedResources = suspend(transaction);
		try {
			boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
			DefaultTransactionStatus status = newTransactionStatus(
					definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
			doBegin(transaction, definition);
			prepareSynchronization(status, definition);
			return status;
		}
	}
	// 如果传播行为是PROPAGATION_NESTED,则对当前事务增加savePoint来实现内嵌事务
	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'");
		}
		// 如果是通过给事务增加savePoint来实现内嵌事务
		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.
			// 否则通过开启新事务来实现内嵌事务功能
			boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
			DefaultTransactionStatus status = newTransactionStatus(
					definition, transaction, true, newSynchronization, debugEnabled, null);
			doBegin(transaction, definition);
			prepareSynchronization(status, definition);
			return status;
		}
	}

	// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
	// 走到这里只有PROPAGATION_SUPPORTS和PROPAGATION_REQUIRED这两种传播行为没有处理
	// 是否需要校验事务的一些参数,通常是true的
	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)"));
			}
		}
		// 如果当前事务是readOnly的,但目标方法上的事务属性时非readOnly,那么抛出异常
		if (!definition.isReadOnly()) {
			if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
				throw new IllegalTransactionStateException("Participating transaction with definition [" +
						definition + "] is not marked as read-only but existing transaction is");
			}
		}
	}
	// 包装一下事务对象,事务属性,是否为新事务状态返回一个TransactionStatus对象
	boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
	return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}

二、suspendedResources

我们来看下Spring事务是如何通过此方法来实现挂起当前线程的

protected final SuspendedResourcesHolder suspend(Object transaction) throws TransactionException {
	// 如果事务同步管理器属于激活状态,则需要多处理一下事务管理器的东西
	if (TransactionSynchronizationManager.isSynchronizationActive()) {
		// 取出事务同步器,清空事务同步管理器,并循环遍历调用下事务同步器的suspend方法
		List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
		try {
			Object suspendedResources = null;
			if (transaction != null) {
				// 挂起事务,将当前事务即ConnectionHolder对象从事务变量中剔除并返回
				suspendedResources = doSuspend(transaction);
			}
			// 取出当前事务的名称,readOnly,隔离级别,是否事务激活状态,并还原事务同步管理器的这些状态
			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);
			// 包装一个事务挂起资源对象的Holder
			return new SuspendedResourcesHolder(
					suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
		}
		catch (RuntimeException ex) {
			// doSuspend failed - original transaction is still active...
			doResumeSynchronization(suspendedSynchronizations);
			throw ex;
		}
		catch (Error err) {
			// doSuspend failed - original transaction is still active...
			doResumeSynchronization(suspendedSynchronizations);
			throw err;
		}
	}
	else if (transaction != null) {
		// Transaction active but no synchronization active.
		// 如果事务管理器属于不激活状态,仅仅挂机当前事务,将当前事务包装成suspendedResources
		Object suspendedResources = doSuspend(transaction);
		return new SuspendedResourcesHolder(suspendedResources);
	}
	else {
		// Neither transaction nor synchronization active.
		// 如果事务管理器属于不激活状态,且没有事务,那啥也做
		return null;
	}
}

三、doSuspend

具体挂机事务的方法:将事务对象中的ConnectionHolder设置为null,同时取出从线程变量中取出ConnectionHolder,并清除

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

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring事务Spring框架中非常重要的特性之一,它提供了对事务的管理和控制。在Spring中,事务码主要涉及到以下几个方面: 1. 事务管理器接口(PlatformTransactionManager):该接口定义了事务管理器的基本操作,如开启事务、提交事务、回滚事务等。不同的数据访问技术(如JDBC、Hibernate、JPA等)有不同的实现类。 2. 事务定义接口(TransactionDefinition):该接口定义了事务的属性,如隔离级别、传播行为、超时时间等。Spring中提供了多种事务定义的实现类,例如DefaultTransactionDefinition。 3. 事务状态接口(TransactionStatus):该接口定义了事务的状态信息,如是否处于活动状态、是否可以提交、是否可以回滚等。Spring中提供了多种事务状态的实现类,例如DefaultTransactionStatus。 4. 事务切面(TransactionAspectSupport):该类是Spring事务的核心类之一,它是一个抽象类,提供了对事务的具体实现。它通过AOP技术为带有@Transactional注解的方法创建代理对象,并在方法执行前后进行事务的开启、提交和回滚等操作。 5. 事务切面的通知类(TransactionInterceptor):该类是Spring事务的通知类之一,实现了MethodInterceptor接口。它负责在方法执行前后执行事务相关的逻辑,如开启事务、提交事务、回滚事务等。 以上是Spring事务码的主要组成部分,通过对这些类的深入理解和研究,可以更好地掌握Spring事务的原理和实现机制。注意,这里只是简单介绍了一些关键的类和接口,实际上Spring事务码非常庞大且复杂。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值