Spring中的7大事务传播特性

Spring七大事务传播特性

前言

Spring 的框架提供了事务管理的机制,让我可以通过@Transactional注解实现事务管理,其涉及到了Spring为了实现事务而提供的七大传播特性,不同的传播特性会有不一样的事务效果。

七大传播特性

在Spring框架中,Spring-tx提供了事务管理的基本功能。

maven

在Spring boot 项目中,可以引入Spring的事务管理,通过maven可以实现:

		<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${version}</version>
        </dependency>

然后在需要代理的方法上加上@Transactional注解,然后指定事务信息即可

@Service
public class TestService {

    @Transactional(rollbackFor = Exception.class)
    public void test(){}
}
传播特性

当使用@Transational注解的时候,可以指明Propagation,默认是Require。
在Spring-tx的org.springframework.transaction.annotation包下,Propagation声明了7中事务传播特性的枚举类,分别是

  1. Require
    支持当前事务,如果当前事务不存在,则创建一个新的事务。即当前有事务,就是用当前事务,如果当前没有事务,就新建一个新的事务。
  2. Require_new
    支持当前事务,如果当前存在当前事务,新建一个新的事务,并挂起当前事务。
  3. Support
    如果当前有事务,就以当前事务执行,如果没有事务,就按照没有事务的方式执行。
  4. Not_Support
    如果当前没有事务,就以非事务的方式执行,如果有事务,就挂起当前事务。
  5. Mandatory(强制的意思)
    如果当前存在事务,就加入当前事务,如果没有事务,则报异常。
  6. Never
    以非事务方式执行,如果存在事务,就抛出异常
  7. Nested
    如果当前存在事务,则嵌套事务,如果不存在,就按照Require属性进行。

源码解读

当我们使用事务的时候,调用的方式,其实以动态代理的方式去执行当前的方法。
然后执行TransactionInterceptor的invoke()的方法:

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

然后调用TransactionInterceptor的父类TransactionAspectSupport的方法invokeWithinTransaction():
这里摘取重要的代码片段

		/**第一部分 **/
		// 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);

这段代码,获取的是事务的相关信息,包括事务的属性、事务管理器等

		/**第二部分**/
		PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
		//获取连接点的唯一标识,类名+方法名
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

		//声明式事务处理
		if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
			//创建TransactionInfo对象,包括处理事务传播特性
			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);
			}

这段代码会把事务相关的信息处理完,核心处理事务传播特性的是

//创建TransactionInfo对象,包括处理事务传播特性
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

处理完之后,会把事务信息封装成一个TransactionInfo实体返回。

		/**第三部分**/
		//成功后事务提交,恢复线程私有的老的事务信息
		commitTransactionAfterReturning(txInfo);

处理事务传播特性createTransactionIfNecessary()的核心代码:

if (txAttr != null) {
	f (tm != null) {
		//处理传播特性,并返回一个TransactionInfo对象
		status = tm.getTransaction(txAttr);
	}else {
		if (logger.isDebugEnabled()) {
			logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
			"] because no transaction manager has been configured");
		}
	}
}

然后在AbstractPlatformTransactionManager的getTransaction()方法中处理传播特性:

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

		//以下逻辑都是当前不存在事务的
		// No existing transaction found -> check propagation behavior to find out how to proceed.
		//当前没有事务,如果事务的传播特性是mandatory,则抛出异常
		if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		//否则,如果是required、requires_new、nested的话,则新建事务
		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;
			}
		}
		//以下是supports、not_supported、never三种,这三种,都是不使用事务的
		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);
		}
	}

基本步骤是:没有定义事务就是用默认事务->通过获取数据库连接获取事务->判断是否有事务->根据是否有事务分别处理

有事务

当前有事务的时候,会调用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()) {
				//在一个已存在的Spring-managed事务内创建一个保存点,
				//使用事务状态通过保存点管理器的api实现
				//通常使用jdbc3.0的保存点,
				// 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.
		//可能是supports,也可能是require这两种传播特性
		//由于这里处理的是,当前有事务,所以,基于这种情况下,require和support都是使用当前事务
		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);
	}

基本思路就是:

  • 如果设置的传播特性是never,那么就抛出异常
  • 如果设置的传播特性是not_support,那么就挂起当前事务
  • 如果设置的传播特性是require_new,那么就挂起当前事务,并新建一个事务
  • 如果设置的传播特性是nested,首先判断是否支持嵌套,不支持就抛出异常,然后设置一个保存点,并返回保存点
  • 然后如果是require或者support,那么就使用当前事务
没有事务
  • 如果设置的传播特性是Mandatory的,那么抛出异常
  • 如果设置的传播特性是require_new、require、nested的,则新建一个事务
  • 如果设置的传播特性是support、not_support、never的,则按照非事务的方式运行。

总结

  • 两个require
    require:有则使用,没有则新建
    require_new:没有则新建一个,有则挂起,并新建一个
  • 两个support
    support:有则使用,没有则非事务
    not_support:不支持事务,事务就挂起
  • 两个异常
    never:有事务,抛异常,没有事务,非事务进行
    Mandatory:没有事务,抛异常,有事务,则使用当前事务
  • 一个嵌套
    有事务就嵌套,没有就新建一个
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值