65、Spring5.x源码之旅六十六深入AOP事务原理三

  • 创建事务信息流程图
  • 传播机制图
  • AbstractPlatformTransactionManager的suspend挂起当前事务
    • DataSourceTransactionManager的doSuspend挂起资源
  • AbstractPlatformTransactionManager的SuspendedResourcesHolder构造方法
  • AbstractPlatformTransactionManager的newTransactionStatus创建事务状态
    • DefaultTransactionStatus创建默认事务状态
  • DataSourceTransactionManager的doBegin开启连接和事务
    • AbstractDriverBasedDataSource的getConnection获取一个连接
  • TransactionSynchronizationManager的bindResource绑定数据源和连接资源

创建事务信息流程图

*

传播机制图

*

AbstractPlatformTransactionManager的suspend挂起当前事务

有些传播机制需要挂起当前事务,比如NOT_SUPPORTEDREQUIRES_NEW。首先会清除所有线程相关的同步状态,如果当前事务存在的话,就进行一些属性的清除,比如清空连接持有器,清空线程私有变量的同步状态,最后把当前事务清除的属性保存到一个SuspendedResourcesHolder里,以便于恢复的时候设置会去。

@Nullable
	protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
   
     
		if (TransactionSynchronizationManager.isSynchronizationActive()) {
   
     
			List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
			try {
   
     
				Object suspendedResources = null;
				if (transaction != null) {
   
     
					suspendedResources = doSuspend(transaction);//挂起的资源,连接持有器
				}
				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);
			}
			catch (RuntimeException | Error ex) {
   
     
				// doSuspend failed - original transaction is still active...
				doResumeSynchronization(suspendedSynchronizations);
				throw ex;
			}
		}
		else if (transaction != null) {
   
     
			// Transaction active but no synchronization active.
			Object suspendedResources = doSuspend(transaction);
			return new SuspendedResourcesHolder(suspendedResources);
		}
		else {
   
     
			// Neither transaction nor synchronization active.
			return null;
		}

DataSourceTransactionManager的doSuspend挂起资源

	@Override
	protected Object doSuspend(Object transaction) {
   
     
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
		txObject.setConnectionHolder(null);//清空连接持有器
		return TransactionSynchronizationManager.unbindResource(obtainDataSource());//解绑线程私有的资源
	}

AbstractPlatformTransactionManager的SuspendedResourcesHolder构造方法

其实就是保存了挂起事务的信息啦。

private SuspendedResourcesHolder(
				@Nullable Object suspendedResources, List<TransactionSynchronization> suspendedSynchronizations,
				@Nullable String name, boolean readOnly, @Nullable Integer isolationLevel, boolean wasActive) {
   
     

			this.suspendedResources = suspendedResources;//连接持有器
			this.suspendedSynchronizations = suspendedSynchronizations;//同步状态
			this.name = name;//方法名
			this.readOnly = readOnly;//是否只读
			this.isolationLevel = isolationLevel;//隔离级别,默认mysql是可重复度,oracle是提交读
			this.wasActive = wasActive;//事务是否激活
		}

AbstractPlatformTransactionManager的newTransactionStatus创建事务状态

这里有个参数很重要newTransaction,是否是新连接,比如当前事务不存在的情况下,肯定是true,但是如果存在,就有可能false,具体还是看传播机制。

	protected DefaultTransactionStatus newTransactionStatus(
			TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
			boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {
   
     
		//是否要新同步,只有要新同步且当前无同步激活事务
		boolean actualNewSynchronization = newSynchronization &&
				!TransactionSynchronizationManager.isSynchronizationActive();
		return new DefaultTransactionStatus(
				transaction, newTransaction, actualNewSynchronization,
				definition.isReadOnly(), debug, suspendedResources);
	}

DefaultTransactionStatus创建默认事务状态

其实就是做个记录,这次事务的状态。

	public DefaultTransactionStatus(
			@Nullable Object transaction, boolean newTransaction, boolean newSynchronization,
			boolean readOnly, boolean debug, @Nullable Object suspendedResources) {
   
     

		this.transaction = transaction;//新创建事务
		this.newTransaction = newTransaction;//是否需要新事务
		this.newSynchronization = newSynchronization;//是否要新同步
		this.readOnly = readOnly;//是否只读
		this.debug = debug;//是否要debug
		this.suspendedResources = suspendedResources;//是否有挂起的连接资源
	}

DataSourceTransactionManager的doBegin开启连接和事务

这里就是开启新连接的地方,如果当前事务没有连接资源了,就会去创建一个新的连接,然后设置连接属性,做一些事务的标记等,表示是一个新的事务了。

@Override
	protected void doBegin(Object transaction, TransactionDefinition definition) {
   
     
		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());//设置是否只读

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

AbstractDriverBasedDataSource的getConnection获取一个连接

其实就是设置用户名和密码,最终是调用JDBC来获取连接。
*
*
*
*

TransactionSynchronizationManager的bindResource绑定数据源和连接资源

这里就是数据源和连接资源的绑定。
*
*

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。