Spring原理篇(17)--Spring事务的传播机制;该篇章是Spring原理篇的最后一章;

因为我们使用了@Trancastional 注解 所以它最终会进来 TransactionInterceptor 也就是上一篇文章 说的Advice 中 执行 invoke方法;

在这里插入图片描述

中间的proceed 就是去执行我们的被代理类的代理方法; 在这过程当中; 我们一步一步分析:在Invoke方法中 return invokeWithinTransaction 该方法点进去 我们一路看下去

@Nullable

protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,

final InvocationCallback invocation) throws Throwable {

“如果事务属性为null,则该方法是非事务性的。”

TransactionAttributeSource tas = getTransactionAttributeSource();

"获取propagation 等配置属性 "

final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);

“获取事务管理器,事务管理器 就是去创建连接 Commit rollback 等一系列操作用的”

final TransactionManager tm = determineTransactionManager(txAttr);

"是否是 ReactiveTransactionManager 管理器;目前笔者没有用过这个管理器; "

“我们在config配置的 是PlatformTransactionManager”

if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {

“该段代码忽略”

“该段代码最后肯定是return的”

return result;

}

“事务管理器 : 可以在Config里面进行配置; 只需要传入dataSource() 就可以”

PlatformTransactionManager ptm = asPlatformTransactionManager™;

final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {

“该方法内部有一个开启了事务的核心方法, 下一自然段我们重点看这个方法”

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

Object retVal;

try {

“执行被代理对象的代理方法;”

retVal = invocation.proceedWithInvocation();

}

catch (Throwable ex) {

"如果报错 进入该方法进行回滚 "

completeTransactionAfterThrowing(txInfo, ex);

“抛出异常”

throw ex;

}

finally {

cleanupTransactionInfo(txInfo);

}

“设置回滚规则,自行配置规则,这里不会诉说”

if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {

“仅当Vavr故障与回滚规则匹配时,才进行et回滚”

TransactionStatus status = txInfo.getTransactionStatus();

if (status != null && txAttr != null) {

retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);

}

}

“提交事务”

commitTransactionAfterReturning(txInfo);

return retVal;

}

“这下面还会return 一种情况”

}

我们先来看 事务传播机制的规则:

Propagation.MANDATORY “强制性”

Propagation.NESTED “嵌套”

Propagation.NEVER “从不”

Propagation.NOT_SUPPORTED “不支持”

Propagation.REQUIRED “默认事务”

Propagation.REQUIRES_NEW “从新再开启一个事务”

Propagation.SUPPORTS “支持”

在说核心方法之前 我们先知道 在传播机制规则中 我们可以配置这7种规则; 这七种规则 我并没有详细说明或者是直接说明它干什么的. 跟着源码 就知道了

createTransactionIfNecessary()方法

============================================================================================

“再其方法内部 这里就是开启事务的核心方法了”

status = tm.getTransaction(txAttr);

getTransaction()方法;

===============================================================================

在这里插入图片描述

public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)

throws TransactionException {

“如果没有给出事务定义,则使用默认值。”

TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());

Object transaction = doGetTransaction();

boolean debugEnabled = logger.isDebugEnabled();

if (isExistingTransaction(transaction)) {

“判断传播机制 这个方法就解释了我们 的传播机制规则; 下面会详细说”

return handleExistingTransaction(def, transaction, debugEnabled);

}

if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {

throw new InvalidTimeoutException(“Invalid transaction timeout”, def.getTimeout());

}

"注意 Propagation.MANDATORY 强制性 就会抛出异常. 它的作用是 手动的开启事务 "

“必须要有事务.如果没有事务 就会抛出异常 . MANDATORY得到了解释 随后总结会进行述说”

if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {

throw new IllegalTransactionStateException(

“No existing transaction found for transaction marked with propagation ‘mandatory’”);

}

"如果 PROPAGATION_REQUIRED PROPAGATION_REQUIRES_NEW TransactionDefinition.PROPAGATION_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;

}

}

…省略部分代码

}

}

startTransaction

============================================================================

private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,

boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {

boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);

DefaultTransactionStatus status = newTransactionStatus(

definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);

“开启事务 看用了什么组件;”

doBegin(transaction, definition);

prepareSynchronization(status, definition);

return status;

}

在这里插入图片描述

这里 我们用了DataSource

@Override

protected void doBegin(Object transaction, TransactionDefinition definition) {

DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;

“申明数据库连接”

Connection con = null;

try {

if (!txObject.hasConnectionHolder() ||

txObject.getConnectionHolder().isSynchronizedWithTransaction()) {

Connection newCon = obtainDataSource().getConnection();

if (logger.isDebugEnabled()) {

logger.debug(“Acquired Connection [” + newCon + “] for JDBC transaction”);

}

txObject.setConnectionHolder(new ConnectionHolder(newCon), true);

}

txObject.getConnectionHolder().setSynchronizedWithTransaction(true);

con = txObject.getConnectionHolder().getConnection();

“设置隔离级别”

Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);

txObject.setPreviousIsolationLevel(previousIsolationLevel);

“设置事务是否可读”

txObject.setReadOnly(definition.isReadOnly());

if (con.getAutoCommit()) {

txObject.setMustRestoreAutoCommit(true);

if (logger.isDebugEnabled()) {

logger.debug(“Switching JDBC Connection [” + con + “] to manual commit”);

}

“关闭事务自动提交!”

con.setAutoCommit(false);

}

}

上面那一段源码 匹配上这段文字了

在这里插入图片描述

主要是设置autoCommit 为false;

接下来 我们看这个方法

再我们的

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 意思是不开启新的数据库连接. "

"我们的事务 实际就是一个一个的数据库连接;我们有两个步骤 一个是先挂起 然后开启新的事务 "

" 这个就是说 我挂起. 但是不开启新的事务;"

“那后面的那个数据库连接 实际上用的就是Jdbc 或者是 Mybatis里面的数据库连接了”

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;

}

}

“PROPAGATION_NESTED 不会去开启新的数据库连接 再数据库里 有一个savepoint的一个说法”

“也就是设置了这个savepoint 我们可以回滚到 某一个点上 例如 我执行A B C 3个sql”

“再B sql 上面我们创建了 savepoint 那么 就会回滚到B sql 这里来;”

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

}

}

// 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”);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值