天天看点

Spring 5.x 源码之旅六十九深入AOP事务原理六处理回滚流程图传播机制图AbstractPlatformTransactionManager的cleanupAfterCompletion回滚后处理

Spring 5.x 源码之旅六十九深入AOP事务原理六

  • 处理回滚流程图
  • 传播机制图
  • AbstractPlatformTransactionManager的cleanupAfterCompletion回滚后处理
    • TransactionSynchronizationManager的clear清除同步状态
    • DataSourceTransactionManager的doCleanupAfterCompletion清除连接相关操作
    • TransactionSynchronizationManager的unbindResource解绑数据源
    • DataSourceUtils的resetConnectionAfterTransaction重置连接
    • DataSourceUtils的releaseConnection释放连接
      • doReleaseConnection释放连接
        • doCloseConnection关闭连接

处理回滚流程图

Spring 5.x 源码之旅六十九深入AOP事务原理六处理回滚流程图传播机制图AbstractPlatformTransactionManager的cleanupAfterCompletion回滚后处理

传播机制图

Spring 5.x 源码之旅六十九深入AOP事务原理六处理回滚流程图传播机制图AbstractPlatformTransactionManager的cleanupAfterCompletion回滚后处理

AbstractPlatformTransactionManager的cleanupAfterCompletion回滚后处理

看上去很像没多少东西,其实里面涉及好多呢,比如如果是新的事务同步状态的话,要把线程的同步状态清除了,如果是新事务的话,进行数据清除,线程的私有资源解绑,重置连接自动提交,隔离级别,是否只读,释放连接等。如果有挂起的事务,还要把这个事务给恢复,其实就是把属性设置回去。

private void cleanupAfterCompletion(DefaultTransactionStatus status) {
		status.setCompleted();
		if (status.isNewSynchronization()) {
			TransactionSynchronizationManager.clear();//线程同步状态清除
		}
		if (status.isNewTransaction()) {//是新事务的话,进行数据清除,线程的私有资源解绑,重置连接自动提交,隔离级别,是否只读,释放连接等
			doCleanupAfterCompletion(status.getTransaction());
		}
		if (status.getSuspendedResources() != null) {//有挂起的事务要恢复
			if (status.isDebug()) {
				logger.debug("Resuming suspended transaction after completion of inner transaction");
			}
			Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
			resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
		}
	}
           

TransactionSynchronizationManager的clear清除同步状态

就是前面我们设置的线程私有的一些属性。

public static void clear() {
		synchronizations.remove();
		currentTransactionName.remove();
		currentTransactionReadOnly.remove();
		currentTransactionIsolationLevel.remove();
		actualTransactionActive.remove();
	}
           

DataSourceTransactionManager的doCleanupAfterCompletion清除连接相关操作

这里就是做跟连接相关的操作,比如重置自动提交啊,只读属性啊,解绑数据源啊,释放连接啊,清除链接持有器属性啊。

@Override
	protected void doCleanupAfterCompletion(Object transaction) {
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;

		// Remove the connection holder from the thread, if exposed.
		if (txObject.isNewConnectionHolder()) {//接触数据源和连接的绑定
			TransactionSynchronizationManager.unbindResource(obtainDataSource());
		}

		// Reset connection.
		Connection con = txObject.getConnectionHolder().getConnection();
		try {
			if (txObject.isMustRestoreAutoCommit()) {
				con.setAutoCommit(true);//充实连接自动提交属性
			}
			DataSourceUtils.resetConnectionAfterTransaction(//重置隔离级别,是否只读等
					con, txObject.getPreviousIsolationLevel(), txObject.isReadOnly());
		}
		catch (Throwable ex) {
			logger.debug("Could not reset JDBC Connection after transaction", ex);
		}

		if (txObject.isNewConnectionHolder()) {
			if (logger.isDebugEnabled()) {
				logger.debug("Releasing JDBC Connection [" + con + "] after transaction");
			}
			DataSourceUtils.releaseConnection(con, this.dataSource);//释放连接
		}
		//连接持有器属性清除
		txObject.getConnectionHolder().clear();
	}
           

TransactionSynchronizationManager的unbindResource解绑数据源

public static Object unbindResource(Object key) throws IllegalStateException {
		//获取数据源
		Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
		Object value = doUnbindResource(actualKey);//获取解绑的连接持有器
		if (value == null) {
			throw new IllegalStateException(
					"No value for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
		}
		return value;
	}
           

其实就是从线程私有变量

resources

中删除了,这个是个

map

,因为可能有多个数据源绑定多个连接的。

Spring 5.x 源码之旅六十九深入AOP事务原理六处理回滚流程图传播机制图AbstractPlatformTransactionManager的cleanupAfterCompletion回滚后处理

DataSourceUtils的resetConnectionAfterTransaction重置连接

其实就是重置事务隔离状态和是否只读。

public static void resetConnectionAfterTransaction(
			Connection con, @Nullable Integer previousIsolationLevel, boolean resetReadOnly) {
		...
		try {
			if (previousIsolationLevel != null) {
				...
				con.setTransactionIsolation(previousIsolationLevel);
			}
			if (resetReadOnly) {
				...
				con.setReadOnly(false);
			}
		}
		catch (Throwable ex) {
			logger.debug("Could not reset JDBC Connection after transaction", ex);
		}
	}
           

DataSourceUtils的releaseConnection释放连接

释放

JDBC

连接。

public static void releaseConnection(@Nullable Connection con, @Nullable DataSource dataSource) {
		try {
			doReleaseConnection(con, dataSource);
		}
		catch (SQLException ex) {
			logger.debug("Could not close JDBC Connection", ex);
		}
		catch (Throwable ex) {
			logger.debug("Unexpected exception on closing JDBC Connection", ex);
		}
	}
           

doReleaseConnection释放连接

获取连接持有器,释放连接,然后关闭连接。

public static void doReleaseConnection(@Nullable Connection con, @Nullable DataSource dataSource) throws SQLException {
		if (con == null) {
			return;
		}
		if (dataSource != null) {
			ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);//获取连接持有器,如果前面解除绑定非就拿不到了
			if (conHolder != null && connectionEquals(conHolder, con)) {//如果连接持有器能拿到的话
				// It's the transactional Connection: Don't close it.
				conHolder.released();
				return;
			}
		}
		doCloseConnection(con, dataSource);//关闭连接
	}
           

doCloseConnection关闭连接

如果不是

SmartDataSource

类型就关闭连接了。

public static void doCloseConnection(Connection con, @Nullable DataSource dataSource) throws SQLException {
		if (!(dataSource instanceof SmartDataSource) || ((SmartDataSource) dataSource).shouldClose(con)) {
			con.close();
		}
	}
           

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

继续阅读