spring 声明式事务源码解析 PROPAGATION_REQUIRES

Posted 会游泳的小猪

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring 声明式事务源码解析 PROPAGATION_REQUIRES相关的知识,希望对你有一定的参考价值。

 当执行到47行的时候,会开启一个事务,此事务叫最新事务(老大事务),然后执行到51行的时候,老大事务会传播给51行的

userService,具体如何实现,请看我分析:

动态代理调用目标方法:

 一直进去会走进 

invokeWithinTransaction 方法,如下图:

 

 重点分析 

TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

如果有 必要就创建事务

 

 分析得到事务状态对象:status = tm.getTransaction(txAttr);

 

 如果是第一个service会走到  

if (isExistingTransaction(transaction)) 为假,就跳过走到下面的代码,开始事务,为最新事务(老大事务),开启事务的同事,会创立一个新的连接,connection
,然后把connection封装到connectionHolder里面,然后把此connnectionHolder放入 threadLocal里面,设置此老大事务为激活状态,并且设置事务状态newTransactin
为true,表示是老大事务。然后运行目标方法,目标方法里面由于 又有另外一个userService, 还是会进入事务的代理代码,会到
if (isExistingTransaction(transaction)) 此时这参数transactin是之前从threadLoacl里面拿到的事务,是之前老大事务留下来的一些属性,所以会任务此时是会存在的,
也就是我们认为的如果当前有事务,就用当前事务,就会进入if条件,走进去
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);
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 {
return startTransaction(definition, transaction, debugEnabled, suspendedResources);
}
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.
return startTransaction(definition, transaction, debugEnabled, null);
}
}

进入
 return startTransaction(definition, transaction, debugEnabled, suspendedResources);

 

 

进入 doBegin

 开启事务,最主要是把connectin自动提交关闭 即代码 

con.setAutoCommit(false);
走完事务代码,然后走目标方法userService,走完以后,由于userService用的事务不是老大事务,所以在执行完目标方法后,提交事务的时候,会判断
状态是不是老大事务,如果不是老大事务就跳过提交(commit)的代码,老大事务判断依据是 newTransaction==true,以及是不是激活状态。然后就会回到
itemService,这个service的目标代码走完以后,就会会到事务代码的提交事务操作,这个时候由于itemService是老大事务,就提交(conmmit),如果在
执行目标方法的时候发生运行时异常,就会进入catch代码块,回滚操作.

以上是关于spring 声明式事务源码解析 PROPAGATION_REQUIRES的主要内容,如果未能解决你的问题,请参考以下文章

Spring AOP源码剖析:Spring声明式事务控制

Spring AOP源码剖析:Spring声明式事务控制

一文解析Spring编程式和声明式事务实例讲解

Spring源码窥探之:声明式事务

spring事务管理 TransactionProxyFactoryBean源码分析

Springday03 AOPSpring声明式事务Spring编程式事务