spring事务传播性源码解析

本文基于spring 5.0.6、spring-tx-5.0.6,由于涉及AOP相关知识,可以先阅读spring aop源码分析代理创建过程

spring中事务可能关注最多的问题就是事务的传播性,7种传播机制如何理解?
在阅读中还注意到一个问题:spring 事务处理中,一个类中的A方法(无事务)调B方法(有事务),事务是否生效?

1. 案例

xml配置

<!-- 配置Spring的事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>
<!-- 注解方式生成事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />

例子

public class TestXmlTransaction {

    @Autowired
    private UserService userService;

    @Test
    public void testXml() {
        userService.doBefore();
    }

}
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserService userService;
    
    @Transactional
    public void realDo() {
        userMapper.updateAddNum(1L, 1);
    }

    public void doBefore() {
        System.out.println("doBefore");
        userService.realDo();
    }
}

2. 代理执行流程

由于我们实现了接口,所以spring为我们创建的代理类为JdkDynamicAopProxy,所以可以先看看其invoke方法执行时候的拦截链
在这里插入图片描述
如果看了开头介绍的文章,可以知道下一步就要进入TransactionInterceptor的invoke方法

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
	public Object invoke(final MethodInvocation invocation) throws Throwable {
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
		// Adapt to TransactionAspectSupport's invokeWithinTransaction...
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}
}

invokeWithinTransaction是在父类TransactionAspectSupport实现的

protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
		final InvocationCallback invocation) throws Throwable {

	// 如果tas为null,则方法为无事务
	TransactionAttributeSource tas = getTransactionAttributeSource();
	final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
	final PlatformTransactionManager tm = determineTransactionManager(txAttr); // 事务管理器
	final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); // 增强的方法名
	// txAttr 表示事务属性,比如method=doBefore为null,而method=realDo时进入这个方法由于已经创建了事务 txAttr就不为空了
	if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
		// 重点:是否需要创建事务
		TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
		Object retVal = null;
		try {
			// 这是个around advice,执行拦截链中下个方法,获取返回值
			retVal = invocation.proceedWithInvocation();
		} catch (Throwable ex) {
			// 处理异常
			completeTransactionAfterThrowing(txInfo, ex);
			throw ex;
		} finally {
			// 清理事务
			cleanupTransactionInfo(txInfo);
		}
		// 事务提交
		commitTransactionAfterReturning(txInfo);
		return retVal;
	}
	// 如果已经拥有事务或者事务管理器为CallbackPreferringPlatformTransactionManager,会走下面
	else {
		final ThrowableHolder throwableHolder = new ThrowableHolder();
		try {
			Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
				// .......
				return invocation.proceedWithInvocation();
			});
			return result;
		} catch (ThrowableHolderException ex) {
			// ......
		}
	}
}

3. 事务传播

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

	// If no name specified, apply method identification as transaction 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) {
			status = tm.getTransaction(txAttr);
		}
		else {
			// log
		}
	}
	return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}

先来看看getTransaction方法中对当前方法没有事务情况的处理

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {

		public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
		Object transaction = doGetTransaction();
	
		if (definition == null) {
			// Use defaults if no transaction definition given.
			definition = new DefaultTransactionDefinition();
		}
		// 重点:是否存在事务 特殊处理
		if (isExistingTransaction(transaction)) {
			// Existing transaction found -> check propagation behavior to find out how to behave.
			return handleExistingTransaction(definition, transaction, debugEnabled);
		}
		if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
			throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
		}
		// 下面是当当前方法不存在事务的处理
		// PROPAGATION_MANDATORY 不存在事务则抛出异常
		if (definition.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 (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
			SuspendedResourcesHolder suspendedResources = suspend(null);
			try {
				boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
				DefaultTransactionStatus status = newTransactionStatus(
						definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
				// 开启事务
				doBegin(transaction, definition);
				prepareSynchronization(status, definition);
				return status;
			} catch (RuntimeException | Error ex) {
				resume(null, suspendedResources);
				throw ex;
			}
		}
		// 剩下的PROPAGATION_SUPPORTS、PROPAGATION_NOT_SUPPORTS、PROPAGATION_NERVER 不创建事务
		else {
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			return prepareTransactionStatus(definition, 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 suspend挂起当前事务,当前方法不使用事务
	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_REQUIRES_NEW suspend挂起当前事务,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;
		} catch (RuntimeException | Error beginEx) {
			resumeAfterBeginException(transaction, suspendedResources, beginEx);
			throw beginEx;
		}
	}
	// PROPAGATION_NESTED 嵌套事务
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
		// ......
		if (useSavepointForNestedTransaction()) {
			DefaultTransactionStatus status =
					prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
			status.createAndHoldSavepoint();
			return status;
		} else {
			boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
			DefaultTransactionStatus status = newTransactionStatus(
					definition, transaction, true, newSynchronization, debugEnabled, null);
			doBegin(transaction, definition);
			prepareSynchronization(status, definition);
			return status;
		}
	}
	// PROPAGATION_REQUIRED、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORY 使用当前事务
	// ......
	boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
	return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}

总结上面的结论可以得到下面表

传播性当前存在事务当前不存在事务
PROPAGATION_REQUIRED(默认)使用当前事务新建事务
PROPAGATION_NEVER抛出异常不创建事务
PROPAGATION_REQUIRED_NEW挂起当前事务,新建事务新建事务
PROPAGATION_SUPPORTS使用当前事务不创建事务
PROPAGATION_NOT_SUPPORTS挂起当前事务不创建事务
PROPAGATION_MANDATORY使用当前事务抛出异常
PROPAGATION_NESTED嵌套事务新建事务

对于PROPAGATION_REQUIRED_NEW和PROPAGATION_NESTED可能会难理解一点,我们用如下伪代码来说明
对于如下代码

// 事务属性 PROPAGATION_REQUIRED
methodA(){
    doSomeThingA();
    methodB();
    doSomeThingB();
}
// 事务属性 在下面定义
methodB(){
}
methodB为PROPAGATION_REQUIRED_NEW

可以用如下代码来简单理解流程

methodA(){
    TransactionManager tm = null;
    try{
        tm = getTransactionManager();
        tm.begin();//开启一个新的事务
        doSomeThing();
        Transaction ts1 = tm.getTransaction();
        tm.suspend();//挂起当前事务
        try{
            tm.begin();//重新开启第二个事务
            Transaction ts2 = tm.getTransaction();
            methodB();
            ts2.commit();//提交第二个事务
        } Catch(RunTimeException ex) {
            ts2.rollback();//回滚第二个事务
        }
        // methodB执行完后,恢复第一个事务
        tm.resume(ts1);
        doSomeThingB();
        ts1.commit();//提交第一个事务
    } catch(RunTimeException ex) {
        ts1.rollback();//回滚第一个事务
    }
}
methodB为PROPAGATION_NESTED

可以用如下代码来简单理解流程

methodA(){
    Connection con = null;
    Savepoint savepoint = null;
    try{
        con = getConnection();
        con.setAutoCommit(false);
        doSomeThingA();
        savepoint = con.setSavepoint();
        try{
            methodB();
        } catch(RuntimeException ex) {
            con.rollback(savepoint);
        }
        doSomeThingB();
        con.commit();
    } catch(RuntimeException ex) {
        con.rollback();
    }
}

问题

上面案例中的realDo是有事务的,但是如果将代码改为如下形式:

@Transactional
public void realDo() {
    userMapper.updateAddNum(1L, 1);
}

public void doBefore() {
    System.out.println("doBefore");
    realDo();
}

这样,doBefore直接调用了realDo,那么realDo方法不会有事务管理。这样就是直接调用方法了,但是如果和案例中的一样,通过获取bean来调用,就会使用代理类,会走spring的事务管理。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值