Spring5 源码阅读笔记(4.1.1.2)handleExistingTransaction(definition, transaction, debugEnabled) 处理存在的事务

每当进入事务切面,Spring 在创建事务的时候都会先新建一个事务对象 DataSourceTransactionObject,见 Spring5 源码阅读笔记(4.1.1.1)doGetTransaction() 拿事务对象。这个事务对象里面有一个 ConnectionHolder,并且这个连接不是新的,newTransaction 为 false。当然,这是默认值,ConnectionHolder 也可能为空。

然后会判断是否已经存在事务,也就是当前事务是一个内层事务。
判断的条件是,前面说的 ConnectionHolder 不为空,且为活跃状态。

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

如果为 true,就会执行本小节的代码。

重点
如果传播方式是 ROPAGATION_REQUIRES_NEW:

  1. 挂起。设置本 DataSourceTransactionObject 的 ConnectionHolder 为空(不用外层事务的连接),解除当前线程与<数据源,连接>的绑定。
  2. 设置状态,是新连接,newTransaction 设置为 true
  3. 获取新连接,关闭自动提交,绑定线程与数据源连接的关系(doBegin)

如果传播方式是 PROPAGATION_NESTED:

  1. 还是用外层事务的连接,newTransaction 设置为 false(本来也是 false)
  2. 创建回滚点(嵌套事务相当于外层事务的一个回滚点)

如果传播方式是默认的,PROPAGATION_REQUIRED:

  1. 还是用外层事务的连接,newTransaction 设置为 false(本来也是 false)

注意:传播方式,是进入切面的按顺序传播,由外到内,在同一层由代码顺序排序。也就是说事务切面在源码中的传播是一条链,是不区别内外层的。前面的总结,从结果上来看来也不算错,但是从源码来说不算准确。

在这里插入图片描述

跟源码
类 AbstractPlatformTransactionManager

private TransactionStatus handleExistingTransaction(
		TransactionDefinition definition, Object transaction, boolean debugEnabled)
		throws TransactionException {

	//不允许有事务,直接异常
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
		throw new IllegalTransactionStateException(
				"Existing transaction found for transaction marked with propagation 'never'");
	}

	//以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
		if (debugEnabled) {
			logger.debug("Suspending current transaction");
		}
		//挂起当前事务
		Object suspendedResources = suspend(transaction);
		boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
		//修改事务状态信息,把事务的一些信息存储到当前线程中,ThreadLocal中
		return prepareTransactionStatus(
				definition, null, false, newSynchronization, debugEnabled, suspendedResources);
	}

	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 {
			boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
			DefaultTransactionStatus status = newTransactionStatus(
					definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
			//见4.1.3 获取新连接,关闭自动提交,绑定数据源和连接的关系
			doBegin(transaction, definition);
			prepareSynchronization(status, definition);
			return status;
		}
		catch (RuntimeException | Error beginEx) {
			resumeAfterBeginException(transaction, suspendedResources, beginEx);
			throw beginEx;
		}
	}

	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.
			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.
	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);
	//默认传播属性,还是用旧连接,true变false
	return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}

跟 suspend:

@Nullable
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
	if (TransactionSynchronizationManager.isSynchronizationActive()) {
		List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
		try {
			Object suspendedResources = null;
			//如果外层事务存在
			if (transaction != null) {
				//把connectionHolder设置为空,拿到挂起的连接
				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

@Override
protected Object doSuspend(Object transaction) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
	//事务对象和连接是挂钩的,如果连接对象设置为空,说明不用上一个事务了
	txObject.setConnectionHolder(null);
	//解除绑定关系,返回的是挂起的连接
	return TransactionSynchronizationManager.unbindResource(obtainDataSource());
}

跟 unbindResource:
类 TransactionSynchronizationManager

public static Object unbindResource(Object key) throws IllegalStateException {
	Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
	Object value = doUnbindResource(actualKey);
	if (value == null) {
		throw new IllegalStateException(
				"No value for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
	}
	//返回的是挂起的连接
	return value;
}

跟 doUnbindResource:

@Nullable
private static Object doUnbindResource(Object actualKey) {
		//<数据源,连接>
	Map<Object, Object> map = resources.get();
	if (map == null) {
		return null;
	}
	Object value = map.remove(actualKey);
	// Remove entire ThreadLocal if empty...
	if (map.isEmpty()) {
		resources.remove();
	}
	// Transparently suppress a ResourceHolder that was marked as void...
	if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
		value = null;
	}
	if (value != null && logger.isTraceEnabled()) {
		logger.trace("Removed value [" + value + "] for key [" + actualKey + "] from thread [" +
				Thread.currentThread().getName() + "]");
	}
	//返回的是挂起的连接
	return value;
}

引用:
关于PROPAGATION_NESTED的理解

org.springframework.transaction.annotation.Transactional和javax.transaction.Transactional是两个不同的事务注解,用于在不同的环境中实现事务管理。 org.springframework.transaction.annotation.Transactional是Spring框架提供的注解,用于标记方法或类,并将其声明为事务性操作。它是Spring中的一部分,用于管理Spring事务。此注解可用于类级别或方法级别,并允许你定义事务的传播行为、隔离级别、超时设置等。这个注解是Spring特有的,不依赖于Java EE规范。 javax.transaction.Transactional是Java EE规范中定义的注解,用于标记方法或类,并将其声明为事务性操作。它是用于管理Java EE应用程序中的事务的一部分。此注解只能在方法级别上使用,并且只能定义事务的传播行为。这个注解是Java EE规范的一部分,不依赖于Spring框架。 因此,主要区别在于它们是属于不同的框架和规范。org.springframework.transaction.annotation.Transactional是Spring框架的一部分,提供了更多的事务管理选项。而javax.transaction.Transactional是Java EE规范中定义的,只提供了基本的事务处理功能。你应该根据你的应用程序环境选择适合的注解。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [关于javax.transaction.Transactional vs org.springframework.transaction.annotation.Transactional](https://blog.csdn.net/JYH1314/article/details/51111876)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值