Spring事物03-源码分析TransactionInterceptor

Spring事物源码分析-TransactionInterceptor

一、TransactionInterceptor

  • Spring声明式事物是基于AOP实现的,如果目标方法存在事物则会对目标对象进行增强代理(JDK/Cglib)
  • TransactionInterceptor则对应的是AOP中的增强器,我们在之前的AOP源码分析中看到很多增强器,比如MethodBeforeAdviceInterceptor对应的是前置增强。而TransactionInterceptor则是事物体系中的增强器。
  • 在事物处理中并不会直接作用与底层的目标对象,而是通过本TransactionInterceptor拦截器来完成事物的一系列操作,包括:创建、提交和回滚等底层操作。

二、主体方法分析

2.1 invoke

  • TransactionInterceptor#invoke方法是最核心的,我们先看看
@Override
	@Nullable
	public Object invoke(final MethodInvocation invocation) throws Throwable {
		// Work out the target class: may be {@code null}.
		// The TransactionAttributeSource should be passed the target class
		// as well as the method, which may be from an interface.
		// 得到代理目标对象
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

		// Adapt to TransactionAspectSupport's invokeWithinTransaction...
		//调用父类TransactionAspectSupport的模板方法
		//执行目标方法invocation.proceed
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}

2.2 invokeWithinTransaction主体方法

  • 核心在父类TransactionAspectSupport#invokeWithinTransaction方法,
  • invokeWithinTransaction内部可以看到整个事物流程的主体,包括声明式事物(关注)和编程式事物(不关注),这里我们先看看整体流程,然后在第三点的步骤方法里面,对这个过程中的每一步骤做具体分析
@Nullable
	protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {

		// If the transaction attribute is null, the method is non-transactional.
		//1.获取事物属性源,(如果为空则表示不存在事物)
		TransactionAttributeSource tas = getTransactionAttributeSource();
		//2.属性源得到目标类和方法有关的属性
		final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
		//3.根据事物属性获取对应的事物管理器,一般是DataSourceTransactionManager
		final PlatformTransactionManager tm = determineTransactionManager(txAttr);
		//4.获取目标方法唯一标识(类.方法,如com.xx.XxImpl.f1方法)
		final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
        //5.根据条件执行目标增强
		if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
			//6.判断是否有必要创建一个事物,根据事物传播行为决定,参考3.1 createTransactionIfNecessary方法分析
			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
			Object retVal = null;
			try {
				// This is an around advice: Invoke the next interceptor in the chain.
				// This will normally result in a target object being invoked.
				//7.回调目标方法,内部执行拦截链调用,并返回结果
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				//8.异常回滚 target invocation exception
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
			    //9.清理工作
				cleanupTransactionInfo(txInfo);
			}
			//10.没有异常,内部提交事物
			commitTransactionAfterReturning(txInfo);
			return retVal;
		}
        //11.else逻辑是编程式事物,不做重点关注
		else {
			 //代码省略,节约篇幅...
		}
	}
  • 这里面代码5处的判断:区别在于声明式事物和编程式事物,后置是没有事物属性的,另外

2.3 主体方法分析

  • 我们根据1.2中invokeWithinTransaction的主体分析,invokeWithinTransaction包含如下几个主要的方法:
createTransactionIfNecessary: 根据情况决定创建事物
proceedWithInvocation:调用目标方法和拦截器链
completeTransactionAfterThrowing:异常回滚
cleanupTransactionInfo:finally保证的清理工作
commitTransactionAfterReturning:事物提交操作
  • 后面我们重点分析这几个方法,

三、步骤分析

3.1 createTransactionIfNecessary

  • TransactionAspectSupport#createTransactionIfNecessary方法判断是否存在事物,根据事物传播行为决定如何动作,核心是通过TransactionStatus来判断事务的属性,内部通过PlatformTransactionManager事物管理器来实现,这里只是做一点控制,关键在getTransaction方法,另外就是prepareTransactionInfo方法,这是两个核心方法;
	protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
			@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {

		// If no name specified, apply method identification as transaction name.
		if (txAttr != null && txAttr.getName() == null) {
			txAttr = new DelegatingTransactionAttribute(txAttr) {
				@Override
				public String getName() {
					return joinpointIdentification;
				}
			};
		}
		TransactionStatus status = null;
		if (txAttr != null) {
			if (tm != null) {
			    //尝试开启一个事物,这里面是关键
				status = tm.getTransaction(txAttr);
			}
			else {
				if (logger.isDebugEnabled()) {
					logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
							"] because no transaction manager has been configured");
				}
			}
		}
		return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
	}
3.1.1 getTransaction
  • AbstractPlatformTransactionManager#AbstractPlatformTransactionManager#getTransaction
	public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
	    //1.调用子类实现来获取一个事物
		Object transaction = doGetTransaction();
        //2.没有事物定义信息就new一个
		if (definition == null) {
			// Use defaults if no transaction definition given.
			definition = new DefaultTransactionDefinition();
		}
        //3.判断是否已存在事物,根据传播属性处理并返回,处理除PROPAGATION_MANDATORY之外的全部可能情况
		if (isExistingTransaction(transaction))
			// Existing transaction found -> check propagation behavior to find out how to behave.
			return handleExistingTransaction(definition, transaction, debugEnabled);
		}

        //4.检查事物超时检查
		if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
			throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
		}
        
        //5.走到这里说明当前没有事物,PROPAGATION_MANDATORY模式下当前没有事物需要抛出异常
		// No existing transaction found -> check propagation behavior to find out how to proceed.
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		//6.若是PROPAGATION_REQUIRED/PROPAGATION_REQUIRES_NEW/PROPAGATION_NESTED类型之一则开启一个新事务
		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);
				//7.如果需要开启事物,先创建一个DefaultTransactionStatus, //后面的回滚、提交等操作是根据这个属性来判断是否在这个TransactionStatus上来进行。 
				DefaultTransactionStatus status = newTransactionStatus(
						definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
				//8.开启事物
				doBegin(transaction, definition);
				//9.事物管理器相关设置
				prepareSynchronization(status, definition);
				return status;
			}
			catch (RuntimeException | Error ex) {
				resume(null, suspendedResources);
				throw ex;
			}
		}
		else {
			// Create "empty" transaction: no actual transaction, but potentially synchronization.
			if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
				logger.warn("Custom isolation level specified but no actual transaction initiated; " +
						"isolation level will effectively be ignored: " + definition);
			}
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
		}
	}
3.1.1.1 doGetTransaction
  • DataSourceTransactionManager#doGetTransaction是子类实现的,查看DataSourceTransactionManager的实现
//根据dataSource获取ConnectionHolder,ConnectionHolder放在TransactionSynchronizationManager的ThreadLocal
//中,
protected Object doGetTransaction() {
		DataSourceTransactionObject txObject = new DataSourceTransactionObject();
		txObject.setSavepointAllowed(isNestedTransactionAllowed());
		ConnectionHolder conHolder =
				(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
		txObject.setConnectionHolder(conHolder, false);
		return txObject;
	}
3.1.1.2 isExistingTransaction
  • DataSourceTransactionManager#isExistingTransaction(transaction):判断是否存在事物,这个方法也是在子类实现的,查看DataSourceTransactionManager的实现
protected boolean isExistingTransaction(Object transaction) {
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
		//1.如果是第一次开启事务这里必然是false,否则将返回true。
		return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
	}
3.1.1.3 handleExistingTransaction
  • AbstractPlatformTransactionManager#handleExistingTransaction()处理已经存在事物的情况
private TransactionStatus handleExistingTransaction(TransactionDefinition definition, 
                    Object transaction, boolean debugEnabled)throws TransactionException {

        //never - 以非事务方式运行,如果有事务存在,抛出异常
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
			throw new IllegalTransactionStateException(
			"Existing transaction found for transaction marked with propagation 'never'");
		}

    	//not_support - 以非事务方式运行,如果有事务存在,挂起当前事务(前面有就挂起、自己不用事物)
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
			//挂起事物
			Object suspendedResources = suspend(transaction);
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			return prepareTransactionStatus(
					definition, null, false, newSynchronization, debugEnabled, suspendedResources);
		}

        //requires_new - 当前必须运行在自己的事物中,如果有事务挂起当前事务,创建一个新的事务
        //(前面有就挂起,自己一定要启动新的事物)
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
		    //挂起事物
			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 | Error beginEx) {
				resumeAfterBeginException(transaction, suspendedResources, beginEx);
				throw beginEx;
			}
		}
        
        //nested - 如果当前事务存在,则嵌套事务执行
        //(当前存在事物则进行事物嵌套,事物可单独回滚或者提交,如果没有事物则和require行为一致)
		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()) {
				// Create savepoint within existing Spring-managed transaction,
				// through the SavepointManager API implemented by TransactionStatus.
				// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
				DefaultTransactionStatus status =
						prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
				status.createAndHoldSavepoint();
				return status;
			}
			else {
				// Nested transaction through nested begin and commit/rollback calls.
				// Usually only for JTA: Spring synchronization might get activated here
				// in case of a pre-existing JTA transaction.
				boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
				DefaultTransactionStatus status = newTransactionStatus(
						definition, transaction, true, newSynchronization, debugEnabled, null);
				doBegin(transaction, definition);
				prepareSynchronization(status, definition);
				return status;
			}
		}

		// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
        //处理PROPAGATION_SUPPORTS或者PROPAGATION_REQUIRED的情况,都需要加入已有的事物
		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);
	}
  • 因为这里面的处理是已经存在事物的情况,因此不需要处理MANDATORY的情况。
3.1.1.4 doBegin
  • DataSourceTransactionManager#doBegin():如果原本没有事物,并且是需要开启事物的三种传播属性之一(PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED),就在该方法开启事物。这个方法也是子类实现的,我们在DataSourceTransactionManager查看实现,另外在包含事物的逻辑处理里面也是用这个方法来开启事物,后面我们再看。
protected void doBegin(Object transaction, TransactionDefinition definition) {
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
		Connection con = null;

		try {
			if (!txObject.hasConnectionHolder() ||
					txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
                //1.从数据源获取连接
				Connection newCon = obtainDataSource().getConnection();
				//2.为当前Transaction设置ConnectionHolder,并且设置newConnectionHolder为true
				txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
			}

			txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
			con = txObject.getConnectionHolder().getConnection();
            //3.根据definition对connection进行一些设置,比如隔离级别
			Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
			txObject.setPreviousIsolationLevel(previousIsolationLevel);

			// 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).
			if (con.getAutoCommit()) {
				txObject.setMustRestoreAutoCommit(true); 
				//4.开启事务,设置autoCommit为false
				con.setAutoCommit(false);
			}

			prepareTransactionalConnection(con, definition);
			txObject.getConnectionHolder().setTransactionActive(true);

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

			// Bind the connection holder to the thread.
			if (txObject.isNewConnectionHolder()) {
			//将当前connection放入TransactionSynchronizationManager中持有,如果下次调用可以判断为已有的事务
				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);
		}
	}
  • 将当前connection放入TransactionSynchronizationManager中持有,最前面的doGetTransaction同一个线程可以获取,再次进入执行的话就会获取到同一个ConnectionHolder,后面的isExistingTransaction方法也可以判定为是已有的transaction。
3.1.2 TransactionAspectSupport#prepareTransactionInfo
  • TransactionAspectSupport#prepareTransactionInfo
protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
			@Nullable TransactionAttribute txAttr, String joinpointIdentification,
			@Nullable TransactionStatus status) {
        //1.创建TransactionInfo
		TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
		if (txAttr != null) {
            //2.设置TransactionStatus
			// The transaction manager will flag an error if an incompatible tx already exists.
			txInfo.newTransactionStatus(status);
		}
		else {
            //2.记录日志,省略...
		}
        //3.事物信息和线程绑定
		txInfo.bindToThread();
		return txInfo;
	}
	
	
    private void bindToThread() {
			// Expose current TransactionStatus, preserving any existing TransactionStatus
			// for restoration after this transaction is complete.
			this.oldTransactionInfo = transactionInfoHolder.get();
			transactionInfoHolder.set(this);
		}
  • 方法主要是生成一个TransactionInfo并绑定到当前线程的ThreadLocal,

3.2 proceedWithInvocation

  • InvocationCallback#proceedWithInvocation:调用目标方法和拦截器链

3.3 completeTransactionAfterThrowing

  • completeTransactionAfterThrowing在目标方法执行期间发生,
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
		if (txInfo != null && txInfo.getTransactionStatus() != null) {
			 
			if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
				try {
				//1.事物回滚
					txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
				}
				catch (TransactionSystemException ex2) {
    			//2.异常处理逻辑,不重点关注
				}
				 
			}
		    //省略其他....
		}
	}

3.4 cleanupTransactionInfo(finally清理)

  • TransactionAspectSupport#cleanupTransactionInfo方法在finally中一定会被调用,清理事物状态
protected void cleanupTransactionInfo(@Nullable TransactionInfo txInfo) {
		if (txInfo != null) {
			txInfo.restoreThreadLocalStatus();
		}
}

3.5 commitTransactionAfterReturning(提交事物)

  • TransactionAspectSupport#commitTransactionAfterReturning: 完成事物提交操作
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
		if (txInfo != null && txInfo.getTransactionStatus() != null) {
            //1.由事物管理器提交事物
			txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
		}
	}
3.5.1 AbstractPlatformTransactionManager#commit
  • 事物管理器提交事物
public final void commit(TransactionStatus status) throws TransactionException {
		//1.已经完成的不能再提交,抛出异常
		if (status.isCompleted()) {
			throw new IllegalTransactionStateException(
					"Transaction is already completed - do not call commit or rollback more than once per transaction");
		}

		DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
		//2.此时说明外层已经抛出异常,那么就回滚
		if (defStatus.isLocalRollbackOnly()) {
			processRollback(defStatus, false);
			return;
		}
        //3.处理回滚的情况
		if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
			if (defStatus.isDebug()) {
				logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
			}
			processRollback(defStatus, true);
			return;
		}
        //4.提交
		processCommit(defStatus);
	}
3.5.2 AbstractPlatformTransactionManager#processCommit
  • 处理事物提交
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
		        //省略...
				else if (status.isNewTransaction()) {
					if (status.isDebug()) {
						logger.debug("Initiating transaction commit");
					}
					unexpectedRollback = status.isGlobalRollbackOnly();
					//事物提交
					doCommit(status);
				}
				//省略...
	}
3.5.3 DataSourceTransactionManager#doCommit
  • 事物提交,底层调用Connection#commit提交事物
protected void doCommit(DefaultTransactionStatus status) {
		//省略...
		try {
			con.commit();
		}
        //省略...
	}

四、典型事物操作

  • 在前面的handleExistingTransaction中,我们有很多事物的操作,比如将事物挂起和恢复,这些和当前的事物传播属性相关。这里我们来看看事物的挂起和恢复的操作

4.1 doSuspend事物挂起

  • DataSourceTransactionManager#doSuspend
  • 对于DataSourceTransactionManager,事务的挂起,就是把当前线程关联的ConnectionHolder解除绑定、
//AbstractPlatformTransactionManager#handleExistingTransaction
private TransactionStatus handleExistingTransaction(TransactionDefinition definition, Object transaction,          boolean debugEnabled)throws TransactionException {
		//省略...
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
			
			Object suspendedResources = suspend(transaction);
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			return prepareTransactionStatus(
					definition, null, false, newSynchronization, debugEnabled, suspendedResources);
	}
	//省略...
}

//AbstractPlatformTransactionManager#suspend

//DataSourceTransactionManager#doSuspend
protected Object doSuspend(Object transaction) {
	DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
	txObject.setConnectionHolder(null);
	return TransactionSynchronizationManager.unbindResource(obtainDataSource());
}

4.2 doResume事物恢复

  • DataSourceTransactionManager#doResume
  • 对于DataSourceTransactionManager,事务的恢复就是把ConnectionHolder再重新绑定到当前线程,继续执行该事务
@Override
	protected void doResume(@Nullable Object transaction, Object suspendedResources) {
		TransactionSynchronizationManager.bindResource(obtainDataSource(), suspendedResources);
	}

五、参考

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值