本文基于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的事务管理。