Spring源码(SpringTransaction):Spring与事务处理,Spring事务处理的设计与实现,Spring事务管理器的设计与实现,Spring声明式事务处理

11 篇文章 2 订阅

Spring与事务处理

JavaEE 应用中的事务处理是一个重要并且涉及范围很广的领域。事务管理的实现往往涉及并发和数据一致性方面的问题。作为应用平台的 Spring,具有在多种环境中配置和使用事务处理的能力,也就是说通过使用 Spring 的事务组件,可以把事务处理的工作统一起来,并为事务处理提供通用的支持。

在涉及单个数据库局部事务的事务处理中,事务的最终实现和数据库的支持是紧密相关的。对局部数据库事务来说,一个事务处理的操作单元往往对应着一系列的数据库操作。数据库产品对这些数据库的 SQL 操作 已经提供了原子性的支持,对 SQL 操作 而言,它的操作结果有两种: 一种是提交成功,数据库操作成功;另一种是回滚,数据库操作不成功,恢复到操作以前的状态。

在事务处理中,事务处理单元的设计与相应的业务逻辑设计有很紧密的联系。在很多情况下,一个业务逻辑处理不会只有一个单独的数据库操作,而是有一组数据库操作。在这个处理过程中,首先涉及的是事务处理单元划分的问题,Spring 借助 IoC 容器 的强大配置能力,为应用提供了声明式的事务划分方式,这种声明式的事务处理,为 Spring 应用 使用事务管理提供了统一的方式。有了 Spring 事务管理 的支持,只需要通过一些简单的配置,应用就能完成复杂的事务处理工作,从而为用户使用事务处理提供很大的方便。

1 Spring 事务处理的设计概览

Spring 事务处理模块的类层次结构如下图所示。
在这里插入图片描述

从上图可以看到,Spring 事务处理模块 是通过 AOP 功能 来实现声明式事务处理的,比如事务属性的配置和读取,事务对象的抽象等。因此,在 Spring 事务处理 中,可以通过设计一个 TransactionProxyFactoryBean 来使用 AOP 功能,通过这个 TransactionProxyFactoryBean 可以生成 Proxy 代理对象,在这个代理对象中,通过 TransactionInterceptor 来完成对代理方法的拦截,正是这些 AOP 的拦截功能,将事务处理的功能编织进来。

对于具体的事务处理实现,比如事务的生成、提交、回滚、挂起等,由于不同的底层数据库有不同的支持方式,因此,在 Spring 事务处理中,对主要的事务实现做了一个抽象和适配。适配的具体事务处理器包括:对 DataSource 数据源 的事务处理支持,对 Hibernate 数据源 的事务处理支持,对 JDO 数据源 的事务处理支持,对 JPA 和 JTA 等数据源的事务处理支持等。这一系列的事务处理支持,都是通过设计 PlatformTransactionManager、AbstractPlatformTransactionManager 以及一系列具体事务处理器来实现的,而 PlatformTransactionManager 又实现了 TransactionInterceptor 接口,通过这样一个接口实现设计,就把这一系列的事务处理的实现与前面提到的 TransactionProxyFactoryBean 结合起来,从而形成了一个 Spring 声明式事务处理 的设计体系。

2 Spring 事务处理 的应用场景

Spring 作为应用平台或框架的设计出发点是支持 POJO 的开发,这点在实现事务处理的时候也不例外。在 Spring 中,它既支持编程式事务管理方式,又支持声明式事务处理方式,在使用 Spring 处理事务的时候,声明式事务处理通常比编程式事务管理更方便些。

Spring 对应用的支持,一方面,通过声明式事务处理,将事务处理的过程和业务代码分离出来。这种声明方式实际上是通过 AOP 的方式来完成的。显然,Spring 已经把那些通用的事务处理过程抽象出来,并通过 AOP 的方式进行封装,然后用声明式的使用方式交付给客户使用。这样,应用程序可以更简单地管理事务,并且只需要关注事务的处理策略。另一方面,应用在选择数据源时可能会采取不同的方案,当以 Spring 作为平台时,Spring 在应用和具体的数据源之间,搭建一个中间平台,通过这个中间平台,解耦应用和具体数据源之间的绑定,并且,Spring 为常用的数据源的事务处理支持提供了一系列的 TransactionManager。这些 Spring 封装好的 TransactionManager 为应用提供了很大的方便,因为在这些具体事务处理过程中,已经根据底层的实现,封装好了事务处理的设置以及与特定数据源相关的特定事务处理过程,这样应用在使用不同的数据源时,可以做到事务处理的即开即用。这样的另一个好处是,如果应用有其他的数据源事务处理需要, Spring 也提供了一种一致的方式。这种 有机的事务过程抽象 和 具体的事务处理 相结合的设计,是我们在日常的开发中非常需要模仿学习的。

Spring事务处理的设计与实现

1 事务处理的编程式使用

    TransactionDefinition td = new DefaultTransactionDefinition();
    // transactionManager 是某一个具体的 PlatformTransactionManager实现类 的对象
    TransactionStatus ts = transactionManager.getTransaction(td);
    try {
        // 这里是需要进行事务处理的方法调用
    }
    catch (Exception e) {
        transactionManager.rollback(ts);
        throw e;
    }
    transactionManager.commit(ts);

在使用编程式事务处理的过程中,利用 DefaultTransactionDefinition 对象 来持有事务处理属性。同时,在创建事务的过程中得到一个 TransactionStatus 对象,然后通过直接调用 transactionManager 对象 的 commit() 和 rollback()方法 来完成事务处理。在这个编程式使用事务管理的过程中,没有看到框架特性的使用,非常简单和直接,很好地说明了事务管理的基本实现过程,以及在 Spring 事务处理实现 中涉及一些主要的类,比如 TransationStatus、TransactionManager 等,对这些类的使用与声明式事务处理的最终实现是一样的。

与编程式使用事务管理不同,在使用声明式事务处理的时候,因为涉及 Spring 框架 对事务处理的统一管理,以及对并发事务和事务属性的处理,所以采用的是一个比较复杂的处理过程,但复杂归复杂,这个过程对使用声明式事务处理的应用来说,基本上是不可见的,而是由 Spring 框架 来完成的。有了这些背景铺垫和前面对 AOP 封装事务处理 的了解,下面来看看 Spring 是如何提供声明式事务处理的,Spring 在这个相对较为复杂的过程中封装了什么。这层封装包括在事务处理中事务的创建、提交和回滚等比较核心的操作。

2 事务的创建

作为声明式事务处理实现的起始点,需要注意 TransactionInterceptor 拦截器 的 invoke()回调 中使用的 createTransactionIfNecessary()方法,这个方法是在 TransactionInterceptor 的基类 TransactionAspectSupport 中实现的。为了了解这个方法的实现,先分析一下 TransactionInterceptor 的基类实现 TransactionAspectSupport,并以这个方法的实现为入口,了解 Spring 是如何根据当前的事务状态和事务属性配置完成事务创建的。

这个 TransactionAspectSupport 的 createTransactionIfNecessary()方法 作为事务创建的入口,其具体的实现时序如下图所示。在 createTransactionIfNecessary()方法 的调用中,会向 AbstractTransactionManager 执行 getTransaction()方法,这个获取 Transaction 事务对象 的过程,在 AbstractTransactionManager 实现 中需要对事务的情况做出不同的处理,然后,创建一个 TransactionStatus,并把这个 TransactionStatus 设置到对应的 TransactionInfo 中去,同时将 TransactionInfo 和当前的线程绑定,从而完成事务的创建过程。createTransactionIfNeccessary()方法 调用中,可以看到两个重要的数据对象 TransactionStatus 和 TransactionInfo 的创建,这两个对象持有的数据是事务处理器对事务进行处理的主要依据,对这两个对象的使用贯穿着整个事务处理的全过程。

链图片转存失败,源站

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
	/**
	 * 根据给定的方法和类,在必要时创建事务
	 */
	@Deprecated
	protected TransactionInfo createTransactionIfNecessary(Method method, Class targetClass) {
		// 根据给定的方法和类获取 TransactionAttribute,
		// 如果 TransactionAttribute 为空,则该方法是非事务性的
		TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
		// 使用确定的事务管理器
		PlatformTransactionManager tm = determineTransactionManager(txAttr);
		return createTransactionIfNecessary(tm, txAttr, methodIdentification(method, targetClass));
	}

	/**
	 * 根据给定的 TransactionAttribute 创建事务
	 */
	@SuppressWarnings("serial")
	protected TransactionInfo createTransactionIfNecessary(
			PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {

		// 如果未指定名称,则使用方法特征作为事务名称
		if (txAttr != null && txAttr.getName() == null) {
			txAttr = new DelegatingTransactionAttribute(txAttr) {
				@Override
				public String getName() {
					return joinpointIdentification;
				}
			};
		}

		// TransactionStatus 封装了事务执行的状态信息
		TransactionStatus status = null;
		if (txAttr != null) {
			if (tm != null) {
				// 根据定义好的 事务方法配置信息TransactionAttribute,通过
				// 平台事务管理器 PlatformTransactionManager 创建事务,同时返回
				// TransactionStatus 来记录当前的事务状态,包括已经创建的事务
				status = tm.getTransaction(txAttr);
			}
			else {
				if (logger.isDebugEnabled()) {
					logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
							"] because no transaction manager has been configured");
				}
			}
		}
		// 准备 TransactionInfo,TransactionInfo对象 封装了事务处理的配置信息以及 TransactionStatus
		return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
	}

	protected TransactionInfo prepareTransactionInfo(PlatformTransactionManager tm,
			TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) {

		TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
		if (txAttr != null) {
			if (logger.isTraceEnabled()) {
				logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
			}
			// 为 TransactionInfo 设置 TransactionStatus,TransactionStatus 持有管理事务处理
			// 需要的数据,如:transaction对象
			// 如果不兼容的 TX 已经存在,事务管理器将标记错误
			txInfo.newTransactionStatus(status);
		}
		else {
			if (logger.isTraceEnabled())
				logger.trace("Don't need to create transaction for [" + joinpointIdentification +
						"]: This method isn't transactional.");
		}

		// 这里把当前的 TransactionInfo 与线程绑定,同时在 TransactionInfo 中由一个变量来保存以前
		// 的 TransactionInfo,这样就持有了一连串与事务处理相关的 TransactionInfo
		// 虽然不一定要创建新的事务,但总会在请求事务时创建 TransactionInfo
		txInfo.bindToThread();
		return txInfo;
	}
}

在以上的处理过程之后,可以看到,具体的事务创建可以交给事务处理器来完成。在事务的创建过程中,已经为事务的管理做好了准备,包括记录事务处理状态,以及绑定事务信息和线程等。下面到事务处理器中去了解一下更底层的事务创建过程。

createTransactionIfNecessary()方法 通过调用 PlatformTransactionManager 的 getTransaction()方法,生成一个 TransactionStatus 对象,封装了底层事务对象的创建。可以看到,AbstractPlatformTransactionManager 提供了创建事务的模板,这个模板会被具体的事务处理器所使用。从下面的代码中可以看到,AbstractPlatformTransactionManager 会根据事务属性配置和当前进程绑定的事务信息,对事务是否需要创建,怎样创建 进行一些通用的处理,然后把事务创建的底层工作交给具体的事务处理器完成。尽管具体的事务处理器完成事务创建的过程各不相同,但是不同的事务处理器对事务属性和当前进程事务信息的处理都是相同的,在 AbstractPlatformTransactionManager 中完成了该实现,这个实现过程是 Spring 提供统一事务处理的一个重要部分。

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {

    //---------------------------------------------------------------------
    // 实现了 PlatformTransactionManager接口 的方法
    // 这里用了一个 模板方法模式,doGetTransaction(), doBegin() 都是交由子类实现的抽象方法
    //---------------------------------------------------------------------
    public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
        // doGetTransaction() 是抽象方法,Transaction对象 的取得由具体的事务管理器
        // 实现,比如:DataSourceTransactionManager
        Object transaction = doGetTransaction();

        // 缓存 debug标志,以避免重复检查
        boolean debugEnabled = logger.isDebugEnabled();

        if (definition == null) {
            // 如果没有给出事务定义,则使用默认值
            definition = new DefaultTransactionDefinition();
        }

        // 检查当前线程是否已经存在事务,如果已经存在事务,则根据事务属性中定义的 事务传播属性配置
        // 来处理事务的产生
        if (isExistingTransaction(transaction)) {
            // 对当前线程中已经有事务存在的情况进行处理,结果封装在 TransactionStatus 中
            return handleExistingTransaction(definition, transaction, debugEnabled);
        }

        // 检查 definition 中 timeout属性 的设置
        if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
            throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
        }

        // 当前没有事务存在,这时需要根据事务属性设置来创建事务
        // 这里可以看到对事务传播属性配置的处理,比如:MANDATORY、REQUIRED、REQUIRES_NEW、NESTED等
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
            throw new IllegalTransactionStateException(
                    "No existing transaction found for transaction marked with propagation 'mandatory'");
        }
        else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
                definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
            definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {

            SuspendedResourcesHolder suspendedResources = suspend(null);
            if (debugEnabled) {
                logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
            }
            try {
                boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
                // 将要返回的 DefaultTransactionStatus对象,封装了事务执行情况
                DefaultTransactionStatus status = newTransactionStatus(
                        definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
                // 创建事务,由具体的事务管理器来完成,如:DataSourceTransactionManager、HibernateTransactionManager
                doBegin(transaction, definition);
                prepareSynchronization(status, definition);
                return status;
            }
            catch (RuntimeException ex) {
                resume(null, suspendedResources);
                throw ex;
            }
            catch (Error err) {
                resume(null, suspendedResources);
                throw err;
            }
        }
        else {
            boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
            return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
        }
    }
}

从上面的代码中可以看到,AbstractTransactionManager 提供的创建事务的实现模板,在这个模板的基础上,具体的事务处理器需要定义自己的实现来完成底层的事务创建工作,比如需要实现 isExistingTransaction() 和 doBegin()方法。关于这些由具体事务处理器实现的方法会在下面结合具体的事务处理器实现,如:DataSourceTransactionManager、HibernateTransactionManager 进行分析。

事务创建的结果是生成一个 TransactionStatus 对象, 通过这个对象来保存事务处理需要的基本信息,这个对象与前面提到过的 TransactionInfo 对象 联系在一起, TransactionStatus 是 TransactionInfo 的一个属性,然后会把 TransactionInfo 保存在 ThreadLocal 对象 里,这样当前线程可以通过 ThreadLocal 对象 取得 TransactionInfo,以及与这个事务对应的 TransactionStatus 对象,从而把事务的处理信息与调用事务方法的当前线程绑定起来。在 AbstractPlatformTransactionManager 创建事务的过程中,可以看到 TransactionStatus 的创建过程。

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {

    /**
     * 通过给定的参数,创建一个 TransactionStatus实例
     */
    protected DefaultTransactionStatus newTransactionStatus(
            TransactionDefinition definition, Object transaction, boolean newTransaction,
            boolean newSynchronization, boolean debug, Object suspendedResources) {

        // 这里判断是不是新事务,如果是新事务,需要把事务属性存放到当前线程中
        // TransactionSynchronizationManager 维护了一系列的 ThreadLocal变量
        // 来保持事务属性,比如,并发事务隔离级别,是否有活跃的事务等
        boolean actualNewSynchronization = newSynchronization &&
                !TransactionSynchronizationManager.isSynchronizationActive();
        // 把结果记录在 DefaultTransactionStatus对象 中并返回
        return new DefaultTransactionStatus(
                transaction, newTransaction, actualNewSynchronization,
                definition.isReadOnly(), debug, suspendedResources);
    }
}

新事务的创建是比较好理解的,这里需要根据事务属性配置进行创建。所谓创建,首先是把创建工作交给具体的事务处理器来完成,比如 DataSourceTransactionManager,把创建的事务对象在 TransactionStatus 中保存下来,然后将其他的事务属性和 线程 ThreadLocal 变量 进行绑定。

相对于创建全新事务的另一种情况是:在创建当前事务时,线程中已经有事务存在了。这种情况同样需要处理,在声明式事务处理中,在当前线程调用事务方法的时候,就会考虑事务的创建处理,这个处理在方法 handleExistingTransaction() 中完成。这里对现有事务的处理,会涉及事务传播属性的具体处理,比如 PROPAGATIONNOT_SUPPORTED、PROPAGATION REQUIRES_ NEW 等。

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {

    /**
     * 为存在的事务创建一个 TransactionStatus实例
     */
    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 表示  以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
        if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
            if (debugEnabled) {
                logger.debug("Suspending current transaction");
            }
            Object suspendedResources = suspend(transaction);
            boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
            // 注意这里的参数,transaction 为 null,newTransaction 为 false,这意味着事务方法不需要
            // 放在事务环境中执行,同时挂起事务的信息记录也保存在 TransactionStatus 中,这里包括了
            // 进程ThreadLocal 对事务信息的记录
            return prepareTransactionStatus(
                    definition, null, false, newSynchronization, debugEnabled, suspendedResources);
        }

        // PROPAGATION_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 {
                boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
                // 挂起事务的信息记录保存在 TransactionStatus 中,这里包括了 进程ThreadLocal 对事务信息的记录
                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;
            }
        }

        // PROPAGATION_NESTED 表示 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,
        // 则执行与 PROPAGATION_REQUIRED 类似的操作
        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()) {
                // 在 Spring 管理的事务中 创建事务保存点
                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 (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");
                }
            }
        }
        // 返回 DefaultTransactionStatus,注意 第三个参数false 代表当前事务方法没有使用新的事务
        boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
        return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
    }
}

3 事务的挂起

事务的挂起牵涉线程与事务处理信息的保存,下面看一下事务挂起的实现。

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {

    /**
     * 挂起给定的事务。先挂起事务同步,然后委托给 doSuspend()方法,子类一般会重写该方法。
     * 该方法返回的 SuspendedResourcesHolder对象,会作为参数传递给 TransactionStatus
     */
    protected final SuspendedResourcesHolder suspend(Object transaction) throws TransactionException {
        if (TransactionSynchronizationManager.isSynchronizationActive()) {
            List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
            try {
                Object suspendedResources = null;
                // 把挂起事务的处理交给具体事务处理器去完成,如果具体的事务处理器不支持事务挂起,
                // 就抛出异常
                if (transaction != null) {
                    suspendedResources = doSuspend(transaction);
                }
                // 这里在线程中保存与事务处理有关的信息,并重置线程中相关的 ThreadLocal变量
                String name = TransactionSynchronizationManager.getCurrentTransactionName();
                TransactionSynchronizationManager.setCurrentTransactionName(null);
                boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
                TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
                Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
                TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
                boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
                TransactionSynchronizationManager.setActualTransactionActive(false);
                return new SuspendedResourcesHolder(
                        suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
            }
            // 若doSuspend()方法出现RuntimeException异常或Error错误,则初始的事务依然存在
            catch (RuntimeException ex) {
                doResumeSynchronization(suspendedSynchronizations);
                throw ex;
            }
            catch (Error err) {
                doResumeSynchronization(suspendedSynchronizations);
                throw err;
            }
        }
        else if (transaction != null) {
            Object suspendedResources = doSuspend(transaction);
            return new SuspendedResourcesHolder(suspendedResources);
        }
        else {
            return null;
        }
    }
}

基于以上内容,就可以完成声明式事务处理的创建了。声明式事务处理能使事务处理应用的开发变得简单,但是简单的背后,蕴含着平台付出的许多努力。

4 事务的提交

下面来看看事务提交是如何实现的。有了前面的对事务创建的分析,下面来分析一下在 Spring 中,声明式事务处理的事务提交是如何完成的。事务提交的调用入口是 TransactionInteceptor 的 invoke()方法,事务提交的具体实现则在其基类 TransactionAspectSupport 的 commitTransactionAfterReturning(TransactionInfo txInfo)方法 中,其中的参数 txInfo 是创建事务时生成的。同时,Spring 的事务管理框架生成的 TransactionStatus 对象 就包含在 TransactionInfo 对象 中。这个 commitTransactionAfterReturning()方法 在 TransactionInteceptor 的实现部分是比较简单的,它通过直接调用事务处理器来完成事务提交。

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {

    /**
     * 在事务方法成功调用后执行,若出现异常,则不执行。如果不创建事务,则不执行任何操作。
     */
    protected void commitTransactionAfterReturning(TransactionInfo txInfo) {
        if (txInfo != null && txInfo.hasTransaction()) {
            if (logger.isTraceEnabled()) {
                logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
            }
            txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
        }
    }
}

与前面分析事务的创建过程一样,我们需要到事务管理器中去看看事务是如何提交的。同样,在 AbstractPlatformTransactionManager 中也有一个模板方法支持具体的事务管理器对事务提交的实现,这个模板方法的实现与前面我们看到的 getTransaction() 很像。

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {

    /**
     * 处理实际提交的事务,这是一个模板方法,其中的 doCommit() 是一个交由子类实现的抽象方法
     */
    private void processCommit(DefaultTransactionStatus status) throws TransactionException {
        try {
            boolean beforeCompletionInvoked = false;
            try {
                // 事务提交的准备工作由具体的事务管理器来完成
                prepareForCommit(status);
                triggerBeforeCommit(status);
                triggerBeforeCompletion(status);
                beforeCompletionInvoked = true;
                boolean globalRollbackOnly = false;
                if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
                    globalRollbackOnly = status.isGlobalRollbackOnly();
                }
                // 嵌套事务的处理
                if (status.hasSavepoint()) {
                    if (status.isDebug()) {
                        logger.debug("Releasing transaction savepoint");
                    }
                    status.releaseHeldSavepoint();
                }
                // 如果当前事务是一个新事务,调用具体事务处理器的 doCommit() 实现;否则,
                // 不提交,由已经存在的事务来完成提交
                else if (status.isNewTransaction()) {
                    if (status.isDebug()) {
                        logger.debug("Initiating transaction commit");
                    }
                    // 该实现由具体的事务管理器来完成
                    doCommit(status);
                }
                // 如果我们有一个全局仅回滚标记,但仍然没有从 commit 中获得相应的异常,
                // 则抛出 UnexpectedRollbackException
                if (globalRollbackOnly) {
                    throw new UnexpectedRollbackException(
                            "Transaction silently rolled back because it has been marked as rollback-only");
                }
            }
            catch (UnexpectedRollbackException ex) {
                // can only be caused by doCommit
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
                throw ex;
            }
            catch (TransactionException ex) {
                // can only be caused by doCommit
                if (isRollbackOnCommitFailure()) {
                    doRollbackOnCommitException(status, ex);
                }
                else {
                    triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
                }
                throw ex;
            }
            catch (RuntimeException ex) {
                if (!beforeCompletionInvoked) {
                    triggerBeforeCompletion(status);
                }
                doRollbackOnCommitException(status, ex);
                throw ex;
            }
            catch (Error err) {
                if (!beforeCompletionInvoked) {
                    triggerBeforeCompletion(status);
                }
                doRollbackOnCommitException(status, err);
                throw err;
            }

            // 触发器 afterCommit()回调,其中抛出的异常已传播到调用方,但该事务仍被视为已提交
            try {
                triggerAfterCommit(status);
            }
            finally {
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
            }

        }
        finally {
            cleanupAfterCompletion(status);
        }
    }
}

可以看到,事务提交的准备都是由具体的事务处理器来实现的。当然,对这些事务提交的处理,需要通过对 TransactionStatus 保存的事务处理的相关状态进行判断。提交过程涉及 AbstractPlatformTransactionManager 中的 doCommit() 和 prepareForCommit()方法,它们都是抽象方法,都在具体的事务处理器中完成实现,在下面对具体事务处理器的实现原理的分析中,可以看到对这些实现方法的具体分析。

5 事务的回滚

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {

    /**
     * 处理实际的事务回滚
     */
    private void processRollback(DefaultTransactionStatus status) {
        try {
            try {
                triggerBeforeCompletion(status);
                // 嵌套事务的回滚处理
                if (status.hasSavepoint()) {
                    if (status.isDebug()) {
                        logger.debug("Rolling back transaction to savepoint");
                    }
                    status.rollbackToHeldSavepoint();
                }
                // 当前事务调用方法中,新建事务的回滚处理
                else if (status.isNewTransaction()) {
                    if (status.isDebug()) {
                        logger.debug("Initiating transaction rollback");
                    }
                    doRollback(status);
                }
                // 当前事务调用方法中,没有新建事务的回滚处理
                else if (status.hasTransaction()) {
                    if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
                        if (status.isDebug()) {
                            logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
                        }
                        doSetRollbackOnly(status);
                    }
                    // 由线程中的前一个事务来处理回滚,这里不执行任何操作
                    else {
                        if (status.isDebug()) {
                            logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
                        }
                    }
                }
                else {
                    logger.debug("Should roll back transaction but cannot - no transaction available");
                }
            }
            catch (RuntimeException ex) {
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
                throw ex;
            }
            catch (Error err) {
                triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
                throw err;
            }
            triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
        }
        finally {
            cleanupAfterCompletion(status);
        }
    }
}

以上对事务的创建、提交和回滚的实现原理进行了分析,这些过程的实现都比较复杂,一方面 这些处理会涉及很多事务属性的处理;另一方面 会涉及事务处理过程中状态的设置,同时在事务处理的过程中,有许多处理也需要根据相应的状态来完成。这样看来,在实现事务处理的基本过程中就会产生许多事务处理的操作分支。

但总的来说,在事务执行的实现过程中,作为执行控制的 TransactionInfo 对象 和 TransactionStatus 对象 特别值得我们注意,比如它们如何与线程进行绑定,如何记录事务的执行情况等。如果大家在配置事务属性时有什么疑惑,不妨直接看看这些事务属性的处理过程,通过对这些实现原理的了解,可以极大地提高对这些事务处理属性使用的理解程度。

1 Spring 事务处理的应用场景

下面,我们以 DataSourceTransactionManager 事务管理器 为例,看一下在具体的事务管理器中如何实现事务创建、提交和回滚这些底层的事务处理操作。DataSourceTransationManager 和其他事务管理器一样,如 JtaTransactionManager,JpaTransactionManager 和 JdoTransactionManager,都继承自 AbstractPlatformManager,作为一个基类,AbstractPlatfromManager 封装了 Spring 事务处理 中通用的处理部分,比如事务的创建、提交、回滚,事务状态和信息的处理,与线程的绑定等,有了这些通用处理的支持,对于具体的事务管理器而言,它们只需要处理和具体数据源相关的组件设置就可以了,比如在 HibernateTransactionManager 中,就只需要配置好和 Hibnernate 事务处理 相关的接口以及相关的设置。所以,从 PlatformTransactionManager 组件 的设计关系上,我们也可以看到,Spring 事务处理 的主要过程是分两个部分完成的,通用的事务处理框架是在 AbstractPlatformManager 中完成,而 Spring 的事务接口与数据源实现的接口,多半是由具体的事务管理器来完成,它们都是作为 AbstractPlatformManager 的子类来是使用的。

可以看到,在 PlatformTransactionManager 组件 的设计中 ,通过 PlatformTransactionManager 接口 设计了一系列与事务处理息息相关的接口方法,如 getTransaction()、commit()、rollback() 这些和事务处理相关的统一接口。对于这些接口的实现,很大一部分是由 AbstractTransactionManager 抽象类 来完成的,这个类中的 doGetTransaction()、doCommit() 等方法和 PlatformTransactionManager 的方法对应,实现的是事务处理中相对通用的部分。在这个 AbstractPlatformManager 下,为具体的数据源配置了不同的事务处理器,以处理不同数据源的事务处理,从而形成了一个从抽象到具体的事务处理中间平台设计,使应用通过声明式事务处理,即开即用事务处理服务,隔离那些与特定的数据源相关的具体实现。

链图片转存失败,源站

2 DataSourceTransactionManager 的实现

我们先看一下 DataSourceTransactionManager,在这个事务管理器中,它的实现直接与事务处理的底层实现相关。在事务开始的时候,会调用 doBegin()方法,首先会得到相对应的 Connection,然后可以根据事务设置的需要,对 Connection 的相关属性进行配置,比如将 Connection 的 autoCommit 功能 关闭,并对像 TimeoutInSeconds 这样的事务处理参数进行设置,最后通过 TransactionSynchronizationManager 来对资源进行绑定。

从下面的代码中可以看到,DataSourceTransactionManager 作为 AbstractPlatformTransactionManager 的子类,在 AbstractPlatformTransactionManager 中已经为事务实现设计好了一系列的模板方法,比如 事务的提交、回滚处理等。在 DataSourceTransactionManager 中, 可以看到对模板方法中一些抽象方法的具体实现。例如,由 DataSourceTransactionManager 的 doBegin()方法 实现负责事务的创建工作。具体来说,如果使用 DataSource 创建事务,最终通过设置 Connection 的 autoCommit 属性 来对事务处理进行配置。在实现过程中,需要把数据库的 Connection 和当前的线程进行绑定。对于事务的提交和回滚,都是通过直接调用 Connection 的提交和回滚来完成的,在这个实现过程中,如何取得事务处理场景中的 Connection 对象,也是一个值得注意的地方。

上面介绍了使用 DataSourceTransactionManager 实现事务创建、提交和回滚的过程,基本上与单独使用 Connection 实现事务处理是一样的,也是通过设置 autoCommit 属性,调用 Connection 的 commit() 和 rollback()方法 来完成的。而我们在声明式事务处理中看到的那些事务处理属性,并不在 DataSourceTransactionManager 中完成,这和我们在前面分析中看到的是一致的。

链图片转存失败,源站

public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean {

    /** 持有 javax.sql.DataSource对象 */
    private DataSource dataSource;

    /**
     * 这里是产生 Transaction对象 的地方,为 Transaction 的创建提供服务,对数据库而言,
     * 事务工作是由 Connection 来完成的。这里把数据库的 Connection对象 放到了 ConnectionHolder 中,
     * 然后封装到一个 DataSourceTransactionObject对象 中,在这个封装过程中增加了许多为事务处理服务的
     * 控制数据
     */
    @Override
    protected Object doGetTransaction() {
        DataSourceTransactionObject txObject = new DataSourceTransactionObject();
        txObject.setSavepointAllowed(isNestedTransactionAllowed());
        // 获取与当前线程绑定的 数据库Connection,这个 Connection 在第一个事务开始
        // 的地方与线程绑定
        ConnectionHolder conHolder =
            (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
        txObject.setConnectionHolder(conHolder, false);
        return txObject;
    }

    /**
     * 判断是否存在活跃的事务,由 ConnectionHolder 的 transactionActive属性 来控制
     */
    @Override
    protected boolean isExistingTransaction(Object transaction) {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
        return (txObject.getConnectionHolder() != null && txObject.getConnectionHolder().isTransactionActive());
    }

    /**
     * 这里是处理事务开始的地方,在这里设置隔离级别,但忽略超时
     */
    @Override
    protected void doBegin(Object transaction, TransactionDefinition definition) {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
        Connection con = null;

        try {
            if (txObject.getConnectionHolder() == null ||
                    txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
                Connection newCon = this.dataSource.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);

            // 这里是 数据库Connection 完成事务处理的重要配置,需要把 autoCommit属性 关掉
            if (con.getAutoCommit()) {
                txObject.setMustRestoreAutoCommit(true);
                if (logger.isDebugEnabled()) {
                    logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
                }
                con.setAutoCommit(false);
            }
            txObject.getConnectionHolder().setTransactionActive(true);

            int timeout = determineTimeout(definition);
            if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
                txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
            }

            // 把当前的 数据库Connection 与线程绑定
            if (txObject.isNewConnectionHolder()) {
                TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
            }
        }

        catch (Throwable ex) {
            DataSourceUtils.releaseConnection(con, this.dataSource);
            throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
        }
    }

    /**
     * 事务提交的具体实现
     */
    @Override
    protected void doCommit(DefaultTransactionStatus status) {
        // 取得 Connection 以后,通过Connection 进行提交
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
        Connection con = txObject.getConnectionHolder().getConnection();
        if (status.isDebug()) {
            logger.debug("Committing JDBC transaction on Connection [" + con + "]");
        }
        try {
            con.commit();
        }
        catch (SQLException ex) {
            throw new TransactionSystemException("Could not commit JDBC transaction", ex);
        }
    }

    /**
     * 事务提交的具体实现,通过 Connection对象 的 rollback()方法 实现
     */
    @Override
    protected void doRollback(DefaultTransactionStatus status) {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
        Connection con = txObject.getConnectionHolder().getConnection();
        if (status.isDebug()) {
            logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
        }
        try {
            con.rollback();
        }
        catch (SQLException ex) {
            throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
        }
    }
}

上面介绍了使用 DataSourceTransactionManager 实现事务创建、提交和回滚的过程,基本上与单独使用 Connection 实现事务处理是一样的,也是通过设置 autoCommit 属性,调用 Connection 的 commit() 和 rollback()方法 来完成的。看到这里,大家一定会觉得非常的熟悉。而我们在声明式事务处理中看到的那些事务处理属性,并不在 DataSourceTransactionManager 中完成,这和我们在前面分析中看到的是一致的。

3 小结

总体来说,从声明式事务的整个实现中我们看到,声明式事务处理完全可以看成是一个具体的 Spring AOP 应用。从这个角度来看,Spring 事务处理 的实现本身就为应用开发者提供了一个非常优秀的 AOP 应用 参考实例。在 Spring 的声明式事务处理中,采用了 IoC 容器 的 Bean 配置 为事务方法调用提供事务属性设置,从而为应用对事务处理的使用提供方便。

有了声明式的使用方式,可以把对事务处理的实现与应用代码分离出来。从 Spring 实现 的角度来看,声明式事务处理的大致实现过程是这样的:在为事务处理配置好 AOP 的基础设施(比如,对应的 Proxy 代理对象 和 事务处理 Interceptor 拦截器对象)之后,首先需要完成对这些事务属性配置的读取,这些属性的读取处理是在 TransactionInterceptor 中实现的,在完成这些事务处理属性的读取之后,Spring 为事务处理的具体实现做好了准备。可以看到,Spring 声明式事务处理 的过程同时也是一个整合事务处理实现到 Spring AOP 和 IoC 容器 中去的过程。我们在整个过程中可以看到下面一些要点,在这些要点中,体现了对 Spring 框架 的基本特性的灵活使用。

  • 如何封装各种不同事务处理环境下的事务处理,具体来说,作为应用平台的 Spring,它没法对应用使用什么样的事务处理环境做出限制,这样,对应用户使用的不同的事务处理器,Spring 事务处理平台 都需要为用户提供服务。这些事务处理实现包括在应用中常见的 DataSource 的 Connection、Hibermate 的 Transaction 等,Spring 事务处理 通过一种统一的方式把它们封装起来,从而实现一个通用的事务处理过程,实现这部分事务处理对应用透明,使应用即开即用。
  • 如何读取事务处理属性值,在事务处理属性正确读取的基础上,结合事务处理代码,从而完成在既定的事务处理配置下,事务处理方法的实现。
  • 如何灵活地使用 Spring AOP 框架,对事务处理进行封装,提供给应用即开即用的声明式事务处理功能。

在这个过程中,有几个 Spring 事务处理 的核心类是我们需要关注的。其中包括 TransactionInterceptor,它是使用 AOP 实现声明式事务处理的拦截器,封装了 Spring 对声明式事务处理实现的基本过程;还包括 TransactionAttributeSource 和 TransactionAttribute 这两个类,它们封装了对声明式事务处理属性的识别,以及信息的读入和配置。我们看到的 TransactionAttribute 对象,可以视为对事务处理属性的数据抽象,如果在使用声明式事务处理的时候,应用没有配置这些属性,Spring 将为用户提供 DefaultTransactionAttribute 对象,该对象提供了默认的事务处理属性设置。

在事务处理过程中,可以看到 TransactionInfoTransactionStatus 这两个对象,它们是存放事务处理信息的主要数据对象,它们通过与线程的绑定来实现事务的隔离性。具体来说,TransactionInfo 对象 本身就像是一个栈,对应着每一次事务方法的调用,它会保存每一次事务方法调用的事务处理信息。值得注意的是,在 TransactionInfo 对象 中,它持有 TransactionStatus 对象,这个 TransactionStatus 是非常重要的。由这个 TransactionStatus 来掌管事务执行的详细信息,包括具体的事务对象、事务执行状态、事务设置状态等。

在事务的创建、启动、提交和回滚的过程中,都需要与这个 TransactionStatus 对象 中的数据打交道。在准备完这些与事务管理有关的数据之后,具体的事务处理是由 事务处理器 TransactionManager 来完成的。在事务处理器完成事务处理的过程中,与具体事务处理器无关的操作都被封装到 AbstractPlatformTransactionManager 中实现了。这个抽象的事务处理器为不同的具体事务处理器提供了通用的事务处理模板,它封装了在事务处理过程中,与具体事务处理器无关的公共的事务处理部分。我们在具体的事务处理器(比如 DataSourceTransactionManager 和 HibernateTransactionManager)的实现中可以看到,最为底层的事务创建、挂起、提交、回滚操作。

在 Spring 中,也可以通过编程式的方法来使用事务处理器,以帮助我们处理事务。在编程式的事务处理使用中, TransactionDefinition 是定义事务处理属性的类。对于事务处理属性,Spring 还提供了一个默认的事务属性 DefaultTransactionDefinition 来供用户使用。这种事务处理方式在实现上看起来比声明式事务处理要简单,但编程式实现事务处理却会造成事务处理与业务代码的紧密耦合,因而不经常被使用。在这里,我们之所以举编程式使用事务处理的例子,是因为通过了解编程式事务处理的使用,可以清楚地了解 Spring 统一实现事务处理的大致过程。

有了这个背景,结合对声明式事务处理实现原理的详细分析,比如在声明式事务处理中,使用 AOP 对事务处理进行封装,对事务属性配置进行的处理,与线程绑定从而处理事务并发,并结合事务处理器的使用等,能够在很大程度上提高我们对整个 Spring 事务处理实现 的理解。

1 设计原理与基本过程

在使用 Spring 声明式事务处理 的时候,一种常用的方法是结合 IoC 容器 和 Spring 已有的 TransactionProxyFactoryBean 对事务管理进行配置,比如,可以在这个 TransactionProxyFactoryBean 中为事务方法配置传播行为、并发事务隔离级别等事务处理属性,从而对声明式事务的处理提供指导。具体来说,在对声明式事务处理的原理分析中,声明式事务处理的实现大致可以分为以下几个部分:

  • 读取和处理在 IoC 容器 中配置的事务处理属性,并转化为 Spring 事务处理 需要的内部数据结构,这里涉及的类是 TransactionAttributeSourceAdvisor,从名字可以看出,它是一个 AOP 通知器,Spring 使用这个通知器来完成对事务处理属性值的处理。处理的结果是,在 IoC 容器 中配置的事务处理属性信息,会被读入并转化成 TransactionAttribute 表示的数据对象,这个数据对象是 Spring 对事物处理属性值的数据抽象,对这些属性的处理是和 TransactionProxyFactoryBean 拦截下来的事务方法的处理结合起来的。
  • Spring 事务处理模块 实现统一的事务处理过程。这个通用的事务处理过程包含处理事务配置属性,以及与线程绑定完成事务处理的过程,Spring 通过 TransactionInfo 和 TransactionStatus 这两个数据对象,在事务处理过程中记录和传递相关执行场景。
  • 底层的事务处理实现。对于底层的事务操作,Spring 委托给具体的事务处理器来完成,这些具体的事务处理器,就是在 IoC 容器 中配置声明式事务处理时,配置的 PlatformTransactionManager 的具体实现,比如 DataSourceTransactionManager 和 HibernateTransactionManager 等。

2 实现分析

2.1 事务处理拦截器的配置

和前面的思路一样,从声明式事务处理的基本用法入手,来了解它的基本实现原理。在使用声明式事务处理的时候,需要在 IoC 容器 中配置 TransactionProxyFactoryBean,见名知义,这是一个 FactoryBean,有一个 getObject()方法。在 IoC 容器 进行注入的时候,会创建 TransactionInterceptor 对象,而这个对象会创建一个 TransactionAttributePointcut,为读取 TransactionAttribute 做准备。在容器初始化的过程中,由于实现了 InitializingBean 接口,因此 AbstractSingletonProxyFactoryBean 会实现 afterPropertiesSet()方法,正是在这个方法实例化了一个 ProxyFactory,建立起 Spring AOP 的应用,在这里,会为这个 ProxyFactory 设置通知、目标对象,并最终返回 Proxy 代理对象。在 Proxy 代理对象 建立起来以后,在调用其代理方法的时候,会调用相应的 TransactionInterceptor 拦截器,在这个调用中,会根据 TransactionAttribute 配置的事务属性进行配置,从而为事务处理做好准备。

从 TransactionProxyFactoryBean 入手,通过代码实现来了解 Spring 是如何通过 AOP 功能 来完成事务管理配置的,Spring 为声明式事务处理的实现所做的一些准备工作:包括为 AOP 配置基础设施,这些基础设施包括设置 拦截器 TransactionInterceptor、通知器 DefaultPointcutAdvisor 或 TransactionAttributeSourceAdvisor。同时,在 TransactionProxyFactoryBean 的实现中, 还可以看到注人进来的 PlatformTransactionManager 和 事务处理属性 TransactionAttribute 等。

/**
 * 代理工厂bean 用于简化声明式事务处理,这是标准 AOP 的一个方便的替代方案
 * 使用单独的TransactionInterceptor定义。
 */
@SuppressWarnings("serial")
public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBean
		implements BeanFactoryAware {

    /** 事务拦截器,通过 AOP 来发挥作用,Spring 在此拦截器中封装了事务处理实现 */
    private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor();

    /** 切面 */
    private Pointcut pointcut;


    /**
     * 通过依赖注入的事务属性以 properties的形式 出现
     * 把从 beandefinition 中读到的事务管理的属性信息注入到 transactionInterceptor
     */
    public void setTransactionManager(PlatformTransactionManager transactionManager) {
        this.transactionInterceptor.setTransactionManager(transactionManager);
    }

    /**
     * 创建 AOP 对事务处理的 advisor
     * 本方法在 IoC容器 完成 Bean的依赖注入时,通过 initializeBean()方法 被调用
     */
    @Override
    protected Object createMainInterceptor() {
        this.transactionInterceptor.afterPropertiesSet();
        if (this.pointcut != null) {
            // 如果自己定义了切面,就使用默认的通知器,并为其配置事务处理拦截器
            return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor);
        }
        else {
            // 如果没定义,则使用 Spring默认的切面,使用 TransactionAttributeSourceAdvisor
            // 作为通知器,并配置拦截器
            return new TransactionAttributeSourceAdvisor(this.transactionInterceptor);
        }
    }

    public void setTransactionAttributes(Properties transactionAttributes) {
        this.transactionInterceptor.setTransactionAttributes(transactionAttributes);
    }

    public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
        this.transactionInterceptor.setTransactionAttributeSource(transactionAttributeSource);
    }

    public void setPointcut(Pointcut pointcut) {
        this.pointcut = pointcut;
    }

    public void setBeanFactory(BeanFactory beanFactory) {
        this.transactionInterceptor.setBeanFactory(beanFactory);
    }
}

以上代码完成了 AOP 配置,对于用户来说,一个值得关心的问题是,Spring 的 TransactionInterceptor 配置 是在什么时候被启动并成为 Advisor 通知器 的一部分的呢?从对 createMainInterceptor()方法 的调用分析中可以看到,这个 createMainInterceptor()方法 在 IoC 容器 完成 Bean 的依赖注入时,通过 initializeBean()方法 被调用,具体的调用过程如下图所示。

在这里插入图片描述

在 TransactionProxyFactoryBean 的父类 AbstractSingletonProxyFactoryBean 中的 afterPropertiesSet()方法,是 Spring 事务处理 完成 AOP 配置 的地方,在建立 TransactionProxyFactoryBean 的事务处理拦截器的时候,首先需要对 ProxyFactoryBean 的 目标 Bean 设置进行检查,如果这个 目标 Bean 的设置是正确的,就会创建一个 ProxyFactory 对象,从而实现 AOP 的使用。在 afterPropertiesSet() 的方法实现中,可以看到为 ProxyFactory 生成代理对象、配置通知器、设置代理接口方法等。

public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
		implements FactoryBean<Object>, BeanClassLoaderAware, InitializingBean {

    private Object target;

    private Class<?>[] proxyInterfaces;

    private Object[] preInterceptors;

    private Object[] postInterceptors;

    /** Default is global AdvisorAdapterRegistry */
    private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();

    private transient ClassLoader proxyClassLoader;

    private Object proxy;

    /**
     * 处理完成 AOP配置,创建 ProxyFactory对象,为其生成代理对象
     * 配置通知器、设置代理接口方法
     */
    public void afterPropertiesSet() {

        // 校验target(目标对象)
        if (this.target == null) {
            throw new IllegalArgumentException("Property 'target' is required");
        }
        if (this.target instanceof String) {
            throw new IllegalArgumentException("'target' needs to be a bean reference, not a bean name as value");
        }
        if (this.proxyClassLoader == null) {
            this.proxyClassLoader = ClassUtils.getDefaultClassLoader();
        }

        // 使用 ProxyFactory 完成 AOP的基本功能,ProxyFactory 提供 proxy对象
        // 并将 TransactionIntercepter 设为 target方法调用的拦截器
        ProxyFactory proxyFactory = new ProxyFactory();

        if (this.preInterceptors != null) {
            for (Object interceptor : this.preInterceptors) {
                proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor));
            }
        }

        // 加入 Advisor通知器,可以加入两种通知器,分别是:
        // DefaultPointcutAdvisor、TransactionAttributeSourceAdvisor
        // 这里通过调用 TransactionProxyFactoryBean实例 的 createMainInterceptor()方法
        // 来生成需要的 Advisors。在 ProxyFactory 的基类 AdvisedSupport 中维护了一个持有 Advisor
        // 的链表LinkedList<Advisor>,通过对这个链表中的元素执行增、删、改等操作,用来管理
        // 配置给 ProxyFactory 的通知器
        proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor()));

        if (this.postInterceptors != null) {
            for (Object interceptor : this.postInterceptors) {
                proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor));
            }
        }

        proxyFactory.copyFrom(this);

        // 这里创建 AOP 的目标源,与在其它地方使用 ProxyFactory 没什么差别
        TargetSource targetSource = createTargetSource(this.target);
        proxyFactory.setTargetSource(targetSource);

        if (this.proxyInterfaces != null) {
            proxyFactory.setInterfaces(this.proxyInterfaces);
        }
        else if (!isProxyTargetClass()) {
            // 需要根据 AOP 基础设施来确定使用哪个接口作为代理
            proxyFactory.setInterfaces(
                    ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(), this.proxyClassLoader));
        }

        // 设置代理对象
        this.proxy = proxyFactory.getProxy(this.proxyClassLoader);
    }
}

DefaultAopProxyFactory 创建 AOP Proxy 的过程在前面分析 AOP 的实现原理 时已分析过,这里就不再重复了。可以看到,通过以上的一系列步骤,Spring 为实现事务处理而设计的 拦截器 TransctionInterceptor 已经设置到 ProxyFactory 生成的 AOP 代理对象 中去了,这里的 TransactionInterceptor 是作为 AOP Advice 的拦截器来实现它的功能的。在 IoC 容器 中,配置其他与事务处理有关的属性,比如,比较熟悉的 transactionManager 和事务处理的属性,也同样会被设置到已经定义好的 TransactionInterceptor 中去。这些属性配置在 TransactionInterceptor,对事务方法进行拦截时会起作用。在 AOP 配置 完成以后,可以看到,在 Spring 声明式事务处理实现 中的一些重要的类已经悄然登场,比如 TransactionAttributeSourceAdvisor 和 TransactionInterceptor,正是这些类通过 AOP 封装了 Spring 对事务处理的基本实现。

2.2 事务处理配置的读入

在 AOP 配置 完成的基础上,以 TransactionAttributeSourceAdvisor 的实现 为入口,了解具体的事务属性配置是如何读入的。

public class TransactionAttributeSourceAdvisor extends AbstractPointcutAdvisor {

    /**
     * 与其它 Advisor 一样,同样需要定义 AOP 中用到的 Interceptor 和 Pointcut
     */
    private TransactionInterceptor transactionInterceptor;

    /**
     * 对于 切面Pointcut,这里使用了一个匿名内部类
     */
    private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
        /**
         * 通过 transactionInterceptor 来得到事务的配置属性,在对 Proxy的方法 进行匹配调用时,
         * 会使用到这些配置属性
         */
        @Override
        protected TransactionAttributeSource getTransactionAttributeSource() {
            return (transactionInterceptor != null ? transactionInterceptor.getTransactionAttributeSource() : null);
        }
    };
}

在声明式事务处理中,通过对目标对象的方法调用进行拦截来实现事务处理的织入,这个拦截通过 AOP 发挥作用。在 AOP 中,对于拦截的启动,首先需要对方法调用是否需要拦截进行判断,而判断的依据是那些在 TransactionProxyFactoryBean 中为目标对象设置的事务属性。也就是说,需要判断当前的目标方法调用是不是一个配置好的并且需要进行事务处理的方法调用。具体来说,这个匹配判断在 TransactionAttributeSourcePointcut 的 matches()方法 中完成,该方法实现 首先把事务方法的属性配置读取到 TransactionAttributeSource 对象 中,有了这些事务处理的配置以后,根据当前方法调用的 Method 对象 和 目标对象,对是否需要启动事务处理拦截器进行判断。

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

    public boolean matches(Method method, Class targetClass) {
        TransactionAttributeSource tas = getTransactionAttributeSource();
        return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
    }
}

在 Pointcut 的 matches()判断过程 中,会用到 TransactionAttributeSource 对象,这个 TransactionAttributeSource 对象 是在对 TransactionInterceptor 进行依赖注入时就配置好的。它的设置是在 TransactionInterceptor 的基类 TransactionAspectSupport 中完成的,配置的是一个 NameMatchTransactionAttributeSource 对象。

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
    /**
     * 设置事务属性,以方法名为 key,事务属性描述符为 value
     * 例如:key = "myMethod", value = "PROPAGATION_REQUIRED,readOnly"
     */
    public void setTransactionAttributes(Properties transactionAttributes) {
        // 可以看到这是一个 NameMatchTransactionAttributeSource 的实现
        NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
        tas.setProperties(transactionAttributes);
        this.transactionAttributeSource = tas;
    }
}

在以上的代码实现中可以看到,NameMatchTransactionAttributeSource 作为 TransactionAttributeSource 的具体实现,是实际完成事务处理属性读入和匹配的地方。在对 事务属性 TransactionAttributes 进行设置时,会从事务处理属性配置中读取事务方法名和配置属性,在得到配置的事务方法名和属性以后,会把它们作为键值对加入到一个 nameMap 中。

在应用调用目标方法的时候,因为这个目标方法已经被 TransactionProxyFactoryBean 代理,所以 TransactionProxyFactoryBean 需要判断这个调用方法是否是事务方法。这个判断的实现,是通过在 NameMatchTransactionAttributeSource 中能否为这个调用方法返回事务属性来完成的。具体的实现过程是这样的:首先,以调用方法名为索引在 nameMap 中查找相应的事务处理属性值,如果能够找到,那么就说明该调用方法和事务方法是直接对应的,如果找不到,那么就会遍历整个 nameMap,对保存在 nameMap 中的每一个方法名,使用 PatternMatchUtils 的 simpleMatch()方法 进行命名模式上的匹配。这里使用 PatternMatchUtils 进行匹配的原因是,在设置事务方法的时候,可以不需要为事务方法设置一个完整的方法名,而可以通过设置方法名的命名模式来完成,比如可以通过对 通配符* 的使用等。所以,如果直接通过方法名没能够匹配上,而通过方法名的命名模式能够匹配上,这个方法也是需要进行事务处理的,相对应地,它所配置的事务处理属性也会从 nameMap 中取出来,从而触发事务处理拦截器的拦截。

public class NameMatchTransactionAttributeSource implements TransactionAttributeSource, Serializable {

    /** key 是方法名,value 是事务属性 */
    private Map<String, TransactionAttribute> nameMap = new HashMap<String, TransactionAttribute>();

    /**
     * 将给定 属性transactionAttributes 解析为 <名称, 属性> 的Map对象。以 方法名称 为 key,
     * 字符串属性定义 为 value,可通过 TransactionAttributeEditor 解析为 TransactionAttribute实例。
     */
    public void setProperties(Properties transactionAttributes) {
        TransactionAttributeEditor tae = new TransactionAttributeEditor();
        Enumeration propNames = transactionAttributes.propertyNames();
        while (propNames.hasMoreElements()) {
            String methodName = (String) propNames.nextElement();
            String value = transactionAttributes.getProperty(methodName);
            tae.setAsText(value);
            TransactionAttribute attr = (TransactionAttribute) tae.getValue();
            addTransactionalMethod(methodName, attr);
        }
    }

    /**
     * 为事务方法添加属性
     */
    public void addTransactionalMethod(String methodName, TransactionAttribute attr) {
        if (logger.isDebugEnabled()) {
            logger.debug("Adding transactional method [" + methodName + "] with attribute [" + attr + "]");
        }
        this.nameMap.put(methodName, attr);
    }

    /**
     * 对调用的方法进行判断,判断它是否是事务方法,如果是事务方法,则取出相应的事务配置属性
     */
    public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
        // 直接通过 方法名 匹配
        String methodName = method.getName();
        TransactionAttribute attr = this.nameMap.get(methodName);

        if (attr == null) {
            // 查找最具体的名称匹配
            String bestNameMatch = null;
            for (String mappedName : this.nameMap.keySet()) {
                if (isMatch(methodName, mappedName) &&
                        (bestNameMatch == null || bestNameMatch.length() <= mappedName.length())) {
                    attr = this.nameMap.get(mappedName);
                    bestNameMatch = mappedName;
                }
            }
        }

        return attr;
    }

    /**
     * 如果给定的方法名与映射的名称匹配,则返回
     */
    protected boolean isMatch(String methodName, String mappedName) {
        return PatternMatchUtils.simpleMatch(mappedName, methodName);
    }
}

通过以上过程可以得到与目标对象调用方法相关的 TransactionAttribute 对象,在这个对象中,封装了事务处理的配置。具体来说,在前面的匹配过程中,如果匹配返回的结果是 null,那么说明当前的调用方法不是一个事务方法,不需要纳入 Spring 统一的事务管理中,因为它并没有配置在 TransactionProxyFactoryBean 的事务处理设置中。如果返回的 TransactionAttribute 对象 不是 null,那么这个返回的 TransactionAttribute 对象 就已经包含了对事务方法的配置信息,对应这个事务方法的具体事务配置也已经读入到 TransactionAttribute 对象 中了,为 TransactionInterceptor 做好了对调用的目标方法添加事务处理的准备。

2.3 事务处理拦截器的设计与实现

在完成以上的准备工作后,经过 TransactionProxyFactoryBean 的 AOP 包装, 此时如果对目标对象进行方法调用,起作用的对象实际上是一个 Proxy 代理对象,对目标对象方法的调用,不会直接作用在 TransactionProxyFactoryBean 设置的目标对象上,而会被设置的事务处理拦截器拦截。而在 TransactionProxyFactoryBean 的 AOP 实现 中,获取 Proxy 对象 的过程并不复杂,TransactionProxyFactoryBean 作为一个 FactoryBean,对这个 Bean 的对象的引用是通过调用其父类 AbstractSingletonProxyFactoryBean 的 getObject()方法 来得到的。

public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig
		implements FactoryBean<Object>, BeanClassLoaderAware, InitializingBean {

    private Object proxy;
    // 返回的是一个 proxy代理对象,这个 proxy 是 ProxyFactory 生成的 AOP代理,
    // 已经封装了对事务处理的拦截器配置
    public Object getObject() {
        if (this.proxy == null) {
            throw new FactoryBeanNotInitializedException();
        }
        return this.proxy;
    }
}

InvocationHandler 的实现类中有一个非常重要的方法 invoke(),该方法是 proxy 代理对象 的回调方法,在调用 proxy 对象 的代理方法时触发这个回调。事务处理拦截器 TransactionInterceptor 中实现了 InvocationHandler 的 invoke()方法,其过程是,首先获得调用方法的事务处理配置;在得到事务处理配置以后,会取得配置的 PlatformTransactionManager,由这个事务处理器来实现事务的创建、提交、回滚操作。

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

        // 在其父类 TransactionAspectSupport 中进行后续的事务处理
        return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
            public Object proceedWithInvocation() throws Throwable {
                return invocation.proceed();
            }
        });
    }
}

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {

    private static final ThreadLocal<TransactionInfo> transactionInfoHolder =
            new NamedThreadLocal<TransactionInfo>("Current aspect-driven transaction");

    protected Object invokeWithinTransaction(Method method, Class targetClass, final InvocationCallback invocation)
            throws Throwable {

        // 获取事务属性,如果属性为空,则该方法是非事务性的
        final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
        final PlatformTransactionManager tm = determineTransactionManager(txAttr);
        final String joinpointIdentification = methodIdentification(method, targetClass);

        // 这里区分不同类型的 PlatformTransactionManager,因为他们的调用方式不同,
        // 对 CallbackPreferringPlatformTransactionManager 来说,需要回调函数
        // 来实现事务的创建和提交,而非 CallbackPreferringPlatformTransactionManager
        // 则不需要
        if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
            // 这里创建事务,同时把创建事务过程中得到的信息放到 TransactionInfo 中,
            // TransactionInfo 是保存当前事务状态的对象
            TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
            Object retVal = null;
            try {
                // 这里的调用使处理沿着拦截器链进行,使最后目标对象的方法得以调用
                retVal = invocation.proceedWithInvocation();
            }
            catch (Throwable ex) {
                // 如果在事务处理方法调用中出现了异常,事务如何进行处理需要
                // 根据具体情况考虑回滚或提交
                completeTransactionAfterThrowing(txInfo, ex);
                throw ex;
            }
            finally {
                // 这里把 与线程绑定的 TransactionInfo 设置为 oldTransactionInfo
                cleanupTransactionInfo(txInfo);
            }
            // 这里通过事务处理器来对事务进行提交
            commitTransactionAfterReturning(txInfo);
            return retVal;
        } else {
            // 使用回调的方式来使用事务处理器
            try {
                Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
                        new TransactionCallback<Object>() {
                            public Object doInTransaction(TransactionStatus status) {
                                TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
                                try {
                                    return invocation.proceedWithInvocation();
                                }
                                catch (Throwable ex) {
                                    if (txAttr.rollbackOn(ex)) {
                                        // RuntimeException 会导致事务回滚
                                        if (ex instanceof RuntimeException) {
                                            throw (RuntimeException) ex;
                                        }
                                        else {
                                            throw new ThrowableHolderException(ex);
                                        }
                                    }
                                    else {
                                        // 如果正常返回,则提交该事务
                                        return new ThrowableHolder(ex);
                                    }
                                }
                                finally {
                                    cleanupTransactionInfo(txInfo);
                                }
                            }
                        });

                // Check result: It might indicate a Throwable to rethrow.
                if (result instanceof ThrowableHolder) {
                    throw ((ThrowableHolder) result).getThrowable();
                }
                else {
                    return result;
                }
            }
            catch (ThrowableHolderException ex) {
                throw ex.getCause();
            }
        }
    }

    /**
     * 用于保存事务信息的不透明对象。子类必须将其传递回该类上的方法,但看不到其内部。
     */
    protected final class TransactionInfo {

        private final PlatformTransactionManager transactionManager;

        private final TransactionAttribute transactionAttribute;

        private final String joinpointIdentification;

        private TransactionStatus transactionStatus;

        private TransactionInfo oldTransactionInfo;

        public TransactionInfo(PlatformTransactionManager transactionManager,
                TransactionAttribute transactionAttribute, String joinpointIdentification) {
            this.transactionManager = transactionManager;
            this.transactionAttribute = transactionAttribute;
            this.joinpointIdentification = joinpointIdentification;
        }
    }
}

以事务提交为例,简要的说明下该过程。在调用代理的事务方法时,因为前面已经完成了一系列 AOP 配置,对事务方法的调用,最终启动
TransactionInterceptor 拦截器 的 invoke()方法。在这个方法中,首先会读取该事务方法的事务属性配置,然后根据事务属性配置以及具体事务处理器的配置来决定采用哪一个事务处理器,这个事务处理器实际上是一个 PlatformTransactionManager。在确定好具体的事务处理器之后,会根据事务的运行情况和事务配置来决定是不是需要创建新的事务。

对于 Spring 而言,事务的管理实际上是通过一个 TransactionInfo 对象 来完成的,在该对象中,封装了事务对象和事务处理的状态信息,这是事务处理的抽象。在这一步完成以后,会对拦截器链进行处理,因为有可能在该事务对象中还配置了除事务处理 AOP 之外的其他拦截器。在结束对拦截器链处理之后,会对 TransactionInfo 中的信息进行更新,以反映最近的事务处理情况,在这个时候,也就完成了事务提交的准备,通过调用 事务处理器 PlatformTransactionManager 的 commitTransactionAfterReturning()方法 来完成事务的提交。这个提交的处理过程已经封装在 PlatformTransactionManager 的事务处理器中了,而与具体数据源相关的处理过程,最终委托给相关的具体事务处理器来完成,比如 DataSourceTransactionManager、Hibermate’TransactionManager 等。

在这个 invoke()方法 的实现中,可以看到整个事务处理在 AOP 拦截器 中实现的全过程。同时,它也是 Spring 采用 AOP 封装事务处理和实现声明式事务处理的核心部分。这部分实现是一个桥梁,它胶合了具体的事务处理和 Spring AOP 框架,可以看成是一个 Spring AOP 应用,在这个桥梁搭建完成以后,Spring 事务处理 的实现就开始了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值