天天看點

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

好了,今天就到這裡了,希望對學習了解有幫助,大神看見勿噴,僅為自己的學習了解,能力有限,請多包涵。

繼續閱讀