Spring 5.x 源碼之旅六十九深入AOP事務原理六
- 處理復原流程圖
- 傳播機制圖
- AbstractPlatformTransactionManager的cleanupAfterCompletion復原後處理
-
- TransactionSynchronizationManager的clear清除同步狀态
- DataSourceTransactionManager的doCleanupAfterCompletion清除連接配接相關操作
- TransactionSynchronizationManager的unbindResource解綁資料源
- DataSourceUtils的resetConnectionAfterTransaction重置連接配接
- DataSourceUtils的releaseConnection釋放連接配接
-
- doReleaseConnection釋放連接配接
-
- doCloseConnection關閉連接配接
處理復原流程圖

傳播機制圖
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
,因為可能有多個資料源綁定多個連接配接的。
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();
}
}
好了,今天就到這裡了,希望對學習了解有幫助,大神看見勿噴,僅為自己的學習了解,能力有限,請多包涵。