• spring事务源码分析结合mybatis源码(二)


    让我们继续上篇,分析下如果有第二个调用进入的过程。

    代码部分主要是下面这个:

    if (isExistingTransaction(transaction)) {
                return handleExistingTransaction(definition, transaction, debugEnabled);
            }
    protected boolean isExistingTransaction(Object transaction) {
            DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
            return (txObject.getConnectionHolder() != null && txObject.getConnectionHolder().isTransactionActive());
        }
    isExistingTransaction这个方法主要是用来判断当前线程是否已经存在一个transaction,并且是active,如果是的话进入handleExistingTransaction方法:
    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) {
                Object suspendedResources = suspend(transaction);
                boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
                return prepareTransactionStatus(
                        definition, null, false, newSynchronization, debugEnabled, suspendedResources);
            }
            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 beginEx) {
                    resumeAfterBeginException(transaction, suspendedResources, beginEx);
                    throw beginEx;
                }
                catch (Error beginErr) {
                    resumeAfterBeginException(transaction, suspendedResources, beginErr);
                    throw beginErr;
                }
            }
    
            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 (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;
                }
            }
            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);
        }

    核心的就是这一块了,让我们对这块来分析下:

    首先根据definition.getPropagationBehavior()属性来判断当前事务属性,比如说当definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW时候,也就是新建一个事务,看其中的代码完全跟之前分析第一个事务开启的时候一样。

    而如果当definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED时候,将新建一个保存点事务。

    否则将执行到最后,也就是当definition.getPropagationBehavior()=TransactionDefinition.PROPAGATION_REQUIRED的时候,将初始化一个TransactionStatus,并且将此TransactionStatus的newTransaction属性置为false。

    其后的调用过程跟上篇分析一致,而提交或者回滚的时候都会根据TransactionStatus进行一些判断。

  • 相关阅读:
    【批处理】for命令
    【批处理】if命令,注释方式
    【批处理】choice命令,call 命令,start 命令,rem
    LoadLibrary加载动态库失败
    编译器如何实现静态变量只初始化一次
    汇编语言中 cs, ds,ss 的区别
    变量在内存中的位置
    call和ret指令
    函数调用
    浮动
  • 原文地址:https://www.cnblogs.com/lcxdever/p/4579126.html
Copyright © 2020-2023  润新知