zoukankan      html  css  js  c++  java
  • 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进行一些判断。

  • 相关阅读:
    程序命名标准规范(自定义与其他标准无关)
    asp.net(C#)excel导入导出类
    CSS 技巧
    sql server 更改端口之后的登入方式
    日志插件 log4net 的使用
    js动态调用方法
    mongodb
    Spring 之工具类中注入bin
    解释:什么是云计算?
    当 ADO.NET 遇上 dynamic
  • 原文地址:https://www.cnblogs.com/lcxdever/p/4579126.html
Copyright © 2011-2022 走看看