Spring事务(spring-tx)源码解析

一、简介

1.1、简介

摘自spring官网Data Access (spring.io)

1.1.3. Spring Framework’s Consistent Programming Mode

Spring解决了全局和本地事务的缺点它允许应用程序开发人员在任何环境中使用一致的编程模型您只需编写一次代码,就可以从不同环境中的不同事务管理策略中受益。Spring框架提供声明式和编程式事务管理。大多数用户更喜欢声明式事务管理,我们在大多数情况下都建议这样做。

通过编程事务管理,开发人员可以使用Spring框架事务抽象,它可以运行在任何底层事务基础设施上。使用首选的声明式模型,开发人员通常很少或不编写与事务管理相关的代码,因此不依赖于Spring Framework事务API或任何其他事务API。

        spring-tx对用户提供统一的声明式事务、编程式事务解决方案,对事务的入口,定义、传播、提交、回滚进行了封装,与业务代码隔离,抽象出事务操作PlatformTransactionManager顶级接口,通过将连接及其他需要同步的资源交由事务同步管理器(TransactionSynchronizationManager->ThreadLocal)管理。应用框架、业务程序,只需要通过TransactionSynchronizationManager获取同步资源,操作数据库,不需要或很少关注事务的相关操作,这些操作由spring-tx接管。

        spring-tx在AbstractPlatformTransactionManager中抽象出了getTransaction(开启事务)、commit(提交事务)、rollback(回滚事务)供用户实现,各需要接入spring-tx的框架、应用程序可通过继承该类实现commit、rollback、doBegin、doSuspend、doResume、doCommit、doRollback.......定制化需求,结合TransactionSynchronizationManager,DataSourceUtils以实现与spring-tx的整合,将事务管理交由spring-tx。

        spring-tx定义了一套事物编程方式。用户在使用时只需要通过@Transaction标明方法,或者通过PlatformTransactionManager使用编程式事务。

1.2、使用

1.2.1、声明式事务
public class TransactionalService {

    @Transactional("order")
    public void setSomething(String name) { ... 
            // 注册事务相关回调回调
            TransactionSynchronizationManager.registerSynchronization(new DemoTransactionSynchronization());
}

    @Transactional("account")
    public void doSomething() { ... }

    @Transactional("reactive-account")
    public Mono<Void> doSomethingReactive() { ... }
}
1.2.2、使用spring的事务监听器
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;

import javax.annotation.Resource;

@Service
public class TransactionCallBackDemo {

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    @Transactional
    public void something() {
//        .......
        applicationEventPublisher.publishEvent(new MyTransactionEvent(new Object()));
    }


    // 定事件
    public class MyTransactionEvent extends ApplicationEvent {

        public MyTransactionEvent(Object event) {
            super(event);
        }

    }

    @Component
    public class MyEventListener {

        @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
        public void onHelloEvent(MyTransactionEvent event) {
            //     something       ........
        }
    }

}

1.2.3、编程式事务
// 可阅读或使用 org.springframework.transaction.support.TransactionTemplate#execute

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

public class TransactionalService {
    PlatformTransactionManager transactionManager;

    public void doSoming() {
        DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
        // 设置事务传播方式
        defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        // 开启事务
        TransactionStatus transactionStatus = transactionManager.getTransaction(defaultTransactionDefinition);
        try{
            // 业务逻辑................
            // 注册事务相关回调回调
            TransactionSynchronizationManager.registerSynchronization(new DemoTransactionSynchronization());
            transactionManager.commit(transactionStatus);
        }catch (Exception | Error e){
            transactionManager.rollback(transactionStatus);
        }
    }

    static class DemoTransactionSynchronization extends TransactionSynchronizationAdapter {
        public DemoTransactionSynchronization() {
            super();
        }

        @Override
        public int getOrder() {
            return super.getOrder();
        }

        @Override
        public void suspend() {
//            super.suspend();
            // doSomthing
        }

        @Override
        public void resume() {
            // doSomthing
        }

        @Override
        public void flush() {
            // doSomthing
        }


        /**
         * 在事务提交之前调用(在“beforeComplement”之前)。
         * 例如,可以将事务性OR映射会话刷新到数据库。此回调并不意味着事务将被实际提交
         * 。在调用此方法之后,仍然可以进行回滚决策。这个回调是为了执行只有在提交仍有机会发生时才相关的工作,
         * 例如将SQL语句刷新到数据库。请注意,异常将传播到提交调用程序,并导致事务回滚。
         * @param readOnly whether the transaction is defined as read-only transaction
         */
        @Override
        public void beforeCommit(boolean readOnly) {
            // doSomthing
        }

        /**
         * 在事务commit/rollback之前调用。可以在事务完成前执行资源清理。
         * 此方法将在beforeCommit之后调用,即使在beforeCommit引发异常时也是如此。
         * 此回调允许在事务完成之前关闭资源,以获得任何结果。
         */
        @Override
        public void beforeCompletion() {
            // doSomthing
        }

        /**
         * 事务提交成功后执行回调。可以在成功提交主事务之后立即执行进一步的操作。
         * 例如,可以提交主交易成功提交后的进一步操作,如确认消息或电子邮件。
         * 注意:事务将已经提交,但事务资源可能仍然处于活动状态并且可以访问。
         * 因此,此时触发的任何数据访问代码仍将“参与”原始事务,允许执行一些清理(不再有提交!)
         * ,除非它明确声明需要在单独的事务中运行。因此:对于从这里调用的任何事务性操作,
         * 请使用PROPAGATION_REQUIRES_NEW。
         */
        @Override
        public void afterCommit() {
            // doSomthing
        }

        @Override
        public void afterCompletion(int status) {
            switch (status){
                case STATUS_COMMITTED:
                    // 已提交
                    break;
                case STATUS_ROLLED_BACK:
                    // 已回滚
                    break;
                case STATUS_UNKNOWN:
                    // 事务未知状态
                    break;
            }
            // 在事务commit/rollback之后调用。可以在事务完成后执行资源清理。
            // 事务将已经提交或回滚,但事务资源可能仍然处于活动状态并且可以访问。
            // 因此,此时触发的任何数据访问代码仍将“参与”原始事务,允许执行一些清理(不再有提交!),
            // 除非它明确声明需要在单独的事务中运行。因此:对于从这里调用的任何事务性操作,
            // 请使用PROPAGATION_REQUIRES_NEW。
        }
    }
}

 ​​​​​

二、核心类

2.1、部分内部核心类

2.1.1、TransactionSynchronization

摘自翻译

事务同步回调的接口。由AbstractPlatformTransactionManager支持。TransactionSynchronization实现可以实现Ordered接口来影响其执行顺序。未实现Ordered接口的同步将附加到同步链的末尾。

2.1.2、TransactionStatus

摘自翻译

表示事务的状态。事务代码可以使用它来检索状态信息,并以编程方式请求回滚(而不是引发导致隐式回滚的异常)。

AbstractPlatformTransactionManager使用的org.springframework.transaction.TransactionStatus接口的默认实现。基于底层“事务对象”的概念。保存AbstractPlatformTransactionManager内部需要的所有状态信息,包括由具体事务管理器实现确定的通用事务对象。支持将与保存点相关的方法委派给实现SavepointManager接口的事务对象。

默认实现org.springframework.transaction.support.DefaultTransactionStatus、SimpleTransactionStatus,通常是用DefaultTransactionStatus。

2.1.3、TransactionDefinition

==org.springframework.transaction.annotation.Transactional#propagation

摘自翻译

定义Spring兼容事务属性的接口。基于类似于EJB CMT属性的传播行为定义。请注意,除非启动实际的新事务,否则不会应用隔离级别和超时设置。由于只有PROPAGATION_REQUIRED、PROPAGATION_QUIRES_NEW和PROPAGATION _NESTED会导致这种情况,因此在其他情况下指定这些设置通常没有意义。此外,请注意,并非所有事务管理器都支持这些高级功能,因此在给定非默认值时可能会引发相应的异常。

 事务传播属性

PROPAGATION_REQUIRED支持当前事务;当前不存在,创建新事务
PROPAGATION_SUPPORTS支持当前事务;当前不存在,以非事务方式运行
PROPAGATION_MANDATORY支持当前事务;当前不存在,抛出异常
PROPAGATION_REQUIRES_NEW创建一个新事务,如果当前事务存在,则挂起该事务
PROPAGATION_NOT_SUPPORTED不支持当前事务,以非事务方式运行
PROPAGATION_NEVER不支持当前事务;如果存在当前事务,则引发异常,事务同步在PROPAGATION_NEVER范围内不可用。
PROPAGATION_NESTED如果存在当前事务,则在嵌套事务中执行,当前不存在,创建新事务

超时属性

==org.springframework.transaction.annotation.Transactional#timeout

默认使用底层数据库超时时间

数据库隔离级别

默认数据库的隔离级别

==org.springframework.transaction.annotation.Transactional#isolation

2.1.4、TransactionSynchronizationManager

事务同步管理器

摘自翻译

管理每个线程的资源和事务同步的中心委托。由资源管理代码使用,但不由典型的应用程序代码使用。

支持每个键一个资源而不覆盖,也就是说,在为同一个键设置新的资源之前,需要删除一个资源。如果同步处于活动状态,则支持事务同步列表。

资源管理代码应该通过getResource检查线程绑定资源,例如JDBC连接或Hibernate会话。这样的代码通常不应该将资源绑定到线程,因为这是事务管理器的职责。另一种选择是,如果事务同步处于活动状态,则在首次使用时延迟绑定,以执行跨越任意数量资源的事务。

事务同步必须由事务管理器通过initSynchronization()和clearSynchronization()激活和停用。

这由AbstractPlatformTransactionManager自动支持,因此也由所有标准Spring事务管理器自动支持,如org.springframework.transaction.jta.JtaTransactionManager和org.springfframework.jdbc.datasource.DataSourceTransactionManager。

资源管理代码应该只在该管理器处于活动状态时注册同步,这可以通过isSynchronizationActive进行检查;否则它应该立即执行资源清理。如果事务同步未处于活动状态,则表示没有当前事务,或者事务管理器不支持事务同步。

例如,同步用于在JTA事务中始终返回相同的资源,例如,任何给定DataSource或SessionFactory的JDBC连接或Hibernate会话。

2.2.5、AbstractPlatformTransactionManager

摘自翻译

实现Spring标准事务工作流的抽象基类,作为具体平台事务管理器(如org.springframework.transaction.jta.JtaTransactionManager)的基础。

该基类提供以下工作流处理:

1.确定是否存在现有事务;

2.应用适当的传播行为;

3.必要时暂停和恢复交易;

4.在提交时检查仅回滚标志;

5.对回滚应用适当的修改(仅限实际回滚或设置回滚);

6.触发已注册的同步回调(如果事务同步处于活动状态)。

子类必须为事务的特定状态实现特定的模板方法,例如:开始、挂起、恢复、提交、回滚。其中最重要的是抽象的,必须通过具体的实施来提供;对于其余部分,提供了默认值,因此重写是可选的。

事务同步是一种注册回调的通用机制

2.2.6、DataSourceUtils 

摘自翻译

提供用于从DataSource获取JDBC连接的静态方法的Helper类。包括对Spring托管事务连接的特殊支持,例如由DataSourceTransactionManager或org.springframework.transaction.jta.JtaTransactionManager管理。由Spring的org.springfframework.jdbc.core.JdbcTemplate、Spring的jdbc操作对象和jdbc DataSourceTransactionManager内部使用。也可以直接在应用程序代码中使用。

2.2、外部核心类

2.2.1、spring-boot自动装配相关类 
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration
2.2.2、AOP相关类
org.springframework.transaction.annotation.EnableTransactionManagement
org.springframework.transaction.annotation.TransactionManagementConfigurationSelector
org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration
org.springframework.transaction.annotation.AnnotationTransactionAttributeSource
org.springframework.transaction.interceptor.TransactionInterceptor
org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor

org.springframework.transaction.annotation.EnableTransactionManagement
org.springframework.transaction.annotation.TransactionManagementConfigurationSelector
org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration
org.springframework.transaction.annotation.AnnotationTransactionAttributeSource

摘自翻译:

org.springframework.transaction.interceptor.TransactionAttributeSource接口的实现,用于处理JDK1.5+注释格式的事务元数据。

这个类读取Spring的JDK 1.5+Transactional注释,并向Spring的事务基础结构公开相应的事务属性。还支持JTA 1.2的javax.transaction.Transactional和EJB3的javax.ejb.TransactionAttribute注释(如果存在)。此类也可以作为自定义TransactionAttributeSource的基类,或者通过TransactionAnnotationParser策略进行自定义。

org.springframework.transaction.interceptor.TransactionInterceptor

摘自翻译:

AOP联盟MethodInterceptor,用于使用公共Spring事务基础设施(PlatformTransactionManager)进行声明性事务管理。

派生自TransactionAspectSupport类,该类包含与Spring的底层事务API的集成。TransactionInterceptor只是按照正确的顺序调用相关的超类方法,如invokeWithinTransaction。

org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor

BeanFactoryTransactionAttributeSourceAdvisor(Advisor)

 1、TransactionAttributeSourcePointcut#match(AOP匹配)

       通过AnnotationTransactionAttributeSource#getTransactionAttribute解析事务属性,以返回的事务属性TransactionAttribute是否为空确定是否对方法进行代理。

        AnnotationTransactionAttributeSource#getTransactionAttribute方法委托适配TransactionAnnotationParser的实现类对事务进行解析,目前spring适配兼容了 jta,spring,Ejb3三种

2、TransactionInterceptor(advice)

      对1中拦截的复合条件的方法进行增强、委托PlatformTransactionManager对事务进行接管实现与业务代码节藕,允许应用程序开发人员在任何环境中使用一致的编程模型您只需编写一次代码,就可以从不同环境中的不同事务管理策略中受益。Spring框架提供声明式和编程式事务管理

 

三、部分核心代码

org.springframework.jdbc.datasource.DataSourceTransactionManager类结构图

引用前面的代码

// 可阅读或使用 org.springframework.transaction.support.TransactionTemplate#execute

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

public class TransactionalService {
    PlatformTransactionManager transactionManager;

    public void doSoming() {
        DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
        // 设置事务传播方式
        defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        // 1.开启事务
        TransactionStatus transactionStatus = transactionManager.getTransaction(defaultTransactionDefinition);
        try{
            // 业务逻辑................
            // 2.注册事务相关回调回调
            TransactionSynchronizationManager.registerSynchronization(new DemoTransactionSynchronization());
            // 3.提交事务
            transactionManager.commit(transactionStatus);
        }catch (Exception | Error e){
             // 4.回滚事务
            transactionManager.rollback(transactionStatus);
        }
    }
}
    
   

1、开启事务org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction

	public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException {

		// Use defaults if no transaction definition given.
		TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
		boolean debugEnabled = logger.isDebugEnabled();

		// 调用模板方法,获取自定义事务对象
		Object transaction = doGetTransaction();
		// 当前是否存在事务
		if (isExistingTransaction(transaction)) {
			// 当前存在事务走事务传播策略
			return handleExistingTransaction(def, transaction, debugEnabled);
		}

		// 检查是否超时
		if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
			throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
		}

		// 检查事务传播属性
		if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		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;
			}
		}
		else {
			// Create "empty" transaction: no actual transaction, but potentially synchronization.
			// 创建一个空事务:无实际事务,但是会用于事务的传播、同步判断
			if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
				logger.warn("Custom isolation level specified but no actual transaction initiated; " +
						"isolation level will effectively be ignored: " + def);
			}
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			// 为给定的参数创建一个新的TransactionStatus,并根据需要初始化事务同步。
			return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
		}
	}

org.springframework.transaction.support.AbstractPlatformTransactionManager#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) {
			if (debugEnabled) {
				logger.debug("Suspending current transaction");
			}
			// 暂停事务,返回 suspendedResources 暂停事务状态信息
			Object suspendedResources = suspend(transaction);
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			// 创建一个新的TransactionStatus用于存储上被暂停事务的suspendedResources信息,
			// 返回TransactionStatus用于下一事务传播节点
			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() + "]");
			}
			// 暂停事务,返回 suspendedResources 暂停事务状态信息
			SuspendedResourcesHolder suspendedResources = suspend(transaction);
			try {
				// 开启一个新事务
				return startTransaction(definition, transaction, debugEnabled, suspendedResources);
			}
			catch (RuntimeException | Error beginEx) {
				resumeAfterBeginException(transaction, suspendedResources, beginEx);
				throw beginEx;
			}
		}

		// 嵌套事务执行
		// 方法A(PROPAGATION_REQUIRES_NEW)方法B(PROPAGATION_NESTED) A->B  A事务是否提交不受B异常影响,B是否提交受A是否异常影响
		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);
				// 创建 savepoint B回滚是回滚到此节点,A可继续操作
				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");
				}
			}
		}
		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
		return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
	}

org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin

根据给定的事务定义,使用语义开始新的事务。不必关心应用传播行为,因为这已经由这个抽象管理器处理了。当事务管理器决定实际启动一个新事务时,就会调用此方法。要么之前没有任何交易,要么之前的交易已经暂停。一个特殊的场景是没有保存点的嵌套事务:如果useSavepointForNestedTransaction()返回“false”,则在必要时将调用此方法来启动嵌套事务。在这种情况下,将有一个活动事务:该方法的实现必须检测到这一点并启动适当的嵌套事务

	protected void doBegin(Object transaction, TransactionDefinition definition) {
		// doGetTransaction 获取的
		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());

			// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
			// so we don't want to do it unnecessarily (for example if we've explicitly
			// configured the connection pool to set it already).
			// 如有必要,请切换到手动提交。在一些JDBC驱动程序中,这是非常昂贵的,所以我们不想做不必要的事情(例如,如果我们已经明确配置了连接池来设置它)
			if (con.getAutoCommit()) {
				txObject.setMustRestoreAutoCommit(true);
				if (logger.isDebugEnabled()) {
					logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
				}
				con.setAutoCommit(false);
			}

			// 如果只读,设置连接为只读
			prepareTransactionalConnection(con, definition);
			// 设置事务状态
			txObject.getConnectionHolder().setTransactionActive(true);
			// 设置超时时间

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

			// 将连接绑定到线程
			if (txObject.isNewConnectionHolder()) {
				TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
			}
		}

		catch (Throwable ex) {
			if (txObject.isNewConnectionHolder()) {
				DataSourceUtils.releaseConnection(con, obtainDataSource());
				txObject.setConnectionHolder(null, false);
			}
			throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
		}
	}

org.springframework.transaction.support.AbstractPlatformTransactionManager#prepareSynchronization

同步当前事务信息

	protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
		if (status.isNewSynchronization()) {
			TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
			TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
					definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?
							definition.getIsolationLevel() : null);
			TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
			TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
			TransactionSynchronizationManager.initSynchronization();
		}
	}

2、注册回调

3、提交事务

        org.springframework.transaction.support.AbstractPlatformTransactionManager#processCommit

private void processCommit(DefaultTransactionStatus status) throws TransactionException {
		try {
			boolean beforeCompletionInvoked = false;

			try {
				boolean unexpectedRollback = false;
				// 提交前预处理
				prepareForCommit(status);
				// 触发事务提交前回调
				triggerBeforeCommit(status);
				// 触发事务完成前回电
				triggerBeforeCompletion(status);
				beforeCompletionInvoked = true;
				// 事务在事务传播过程中保存过 savePoint 释放
				if (status.hasSavepoint()) {
					if (status.isDebug()) {
						logger.debug("Releasing transaction savepoint");
					}
					unexpectedRollback = status.isGlobalRollbackOnly();
					status.releaseHeldSavepoint();
				}
				// 是后新建事务,在事务传播过程中,根据不同的传播策略,新建不同的TransactionStatus
				// 不同的TransactionStatus执行不同的提交回滚策略
				else if (status.isNewTransaction()) {
					if (status.isDebug()) {
						logger.debug("Initiating transaction commit");
					}
					unexpectedRollback = status.isGlobalRollbackOnly();
					doCommit(status);
				}
				// 是否被标记为RollbackOnly
				else if (isFailEarlyOnGlobalRollbackOnly()) {
					unexpectedRollback = status.isGlobalRollbackOnly();
				}

				// Throw UnexpectedRollbackException if we have a global rollback-only
				// marker but still didn't get a corresponding exception from commit.
				// 如果我们有一个仅全局回滚的标记,但仍然没有从提交中获得相应的异常,则抛出UnexpectedRollbackException。
				if (unexpectedRollback) {
					throw new UnexpectedRollbackException(
							"Transaction silently rolled back because it has been marked as rollback-only");
				}
			}
			// 被标记为全局回滚异常
			catch (UnexpectedRollbackException ex) {
				// can only be caused by doCommit
				// 触发org.springframework.transaction.support.TransactionSynchronization.afterCompletion回调
				triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
				throw ex;
			}
			// 事务异常
			catch (TransactionException ex) {
				// can only be caused by doCommit
				if (isRollbackOnCommitFailure()) {
					// 触发org.springframework.transaction.support.TransactionSynchronization.afterCompletion回调
					doRollbackOnCommitException(status, ex);
				}
				else {
					// 触发org.springframework.transaction.support.TransactionSynchronization.afterCompletion回调  
					// TransactionSynchronization.STATUS_UNKNOWN
					triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
				}
				throw ex;
			}
			// 未知异常
			catch (RuntimeException | Error ex) {
				if (!beforeCompletionInvoked) {
					// 触发org.springframework.transaction.support.TransactionSynchronization.beforeCompletion
					triggerBeforeCompletion(status);
				}
				// 触发org.springframework.transaction.support.TransactionSynchronization.afterCompletion回调
				doRollbackOnCommitException(status, ex);
				throw ex;
			}

			// Trigger afterCommit callbacks, with an exception thrown there
			// propagated to callers but the transaction still considered as committed.
			try {
				triggerAfterCommit(status);
			}
			finally {
				triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
			}

		}
		finally {
			// 归还资源,同步上一被暂停的事务
			cleanupAfterCompletion(status);
		}
	}

4、回滚事务

org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback

	private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
		try {
			boolean unexpectedRollback = unexpected;

			try {
				// 触发回调
				triggerBeforeCompletion(status);
				// 存在Savepoint 回滚到Savepoint
				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");
							}
							// 标记当前事务为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");
					}
					// Unexpected rollback only matters here if we're asked to fail early
					if (!isFailEarlyOnGlobalRollbackOnly()) {
						unexpectedRollback = false;
					}
				}
			}
			catch (RuntimeException | Error ex) {
				triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
				throw ex;
			}
			// 触发回调
			triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);

			// Raise UnexpectedRollbackException if we had a global rollback-only marker
			if (unexpectedRollback) {
				throw new UnexpectedRollbackException(
						"Transaction rolled back because it has been marked as rollback-only");
			}
		}
		finally {
			// 归还资源,同步被暂停的事务
			cleanupAfterCompletion(status);
		}
	}

四、事务传播解读

MethodA调用MethodB MethodA(默认)和MethodB(PROPAGATION_REQUIRES_NEW)分别使用不同的事务传播策略

MethodA执行:

当前不存在事务,根据传播策略,

        1、MethodA开启事务,同步连接信息到线程(TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder()))以及当前运行事务状态信息。

        2、返回DefaultTransactionStatus。

MethodB执行:

当前存在事务,根据传播策略是否暂停当前事务,MethodB传播方式为PROPAGATION_REQUIRES_NEW,

        1、挂起当前事务,将当前事务状态信息,连接信息,封装成SuspendedResourcesHolder对象

        2、新建DefaultTransactionStatus,将封装的SuspendedResourcesHolder联同newTransaction=true作为构造参数传入 ;

        3、开启新事务,同步新开事务的连接信息以及开启事务的状态相关信息,返回DefaultTransactionStatus

此时通过DatasourceUtils或TransactionSynchronizationManager获取的连接,或状态信息为MethodB新开事务信息

MethodB提交事务:

没有savePoint,触发相关回调,是新事务,提交事务,触发相关回调,归还释放相关资源,根据SuspendedResourcesHolder同步被暂停的事务状态信息以及连接信息;

此时通过DatasourceUtils或TransactionSynchronizationManager获取的连接,或状态信息为被恢复MethodA的事务信息

MethodA 提交事务:

释放资源,清空当前事务状态信息 

五、mybatis整合

mybatis对外提供事务的对接接口org.apache.ibatis.transaction.Transaction从中获取连接,提交回滚事务,org.mybatis.spring.transaction.SpringManagedTransaction该类实现了该接口

获取连接是通过spring-tx提供的工具类org.springframework.jdbc.datasource.DataSourceUtils,从事务同步管理器org.springframework.transaction.support.TransactionSynchronizationManager中获取。

这样mybatis就只需要关注使用获取到的连接操作DB,不需要关注事务的传播,事务的编程方式,关于事务的操作就全部托管给Spring-tx管理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值