spring事務管理源碼解析之事務提交和回滾

本文轉自「天河聊技術」微信公衆號spring

 

說在前面數據庫

@Transactional實現,接着上篇文章繼續微信

正文ide

事務回滾源碼解析this

上次解析到這個方法org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction的這一行debug

 

執行事務方法code

retVal = invocation.proceedWithInvocation();
catch (Throwable ex) {
   // target invocation exception 執行業務方法異常
   completeTransactionAfterThrowing(txInfo, ex);
   throw ex;
}

進入到這個方法orm

org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowing事務

protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
      if (txInfo != null && txInfo.getTransactionStatus() != null) {
         if (logger.isTraceEnabled()) {
            logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
                  "] after exception: " + ex);
         }
//       有指定的異常回滾,異常類型是檢查異常或者是非檢查異常,非檢查性異常自動回滾
         if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
            try {
//             事務回滾
               txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
            }
            catch (TransactionSystemException ex2) {
               logger.error("Application exception overridden by rollback exception", ex);
               ex2.initApplicationException(ex);
               throw ex2;
            }
            catch (RuntimeException | Error ex2) {
               logger.error("Application exception overridden by rollback exception", ex);
               throw ex2;
            }
         }
         else {
            // We don't roll back on this exception.
            // Will still roll back if TransactionStatus.isRollbackOnly() is true.
            try {
               txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
            }
            catch (TransactionSystemException ex2) {
               logger.error("Application exception overridden by commit exception", ex);
               ex2.initApplicationException(ex);
               throw ex2;
            }
            catch (RuntimeException | Error ex2) {
               logger.error("Application exception overridden by commit exception", ex);
               throw ex2;
            }
         }
      }
   }
事務回滾
               txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());

進入到這個方法ip

org.springframework.transaction.support.AbstractPlatformTransactionManager#rollback

@Override
   public final void rollback(TransactionStatus status) throws TransactionException {
//    事務是否已經完成
      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;
//    執行事務回滾
      processRollback(defStatus, false);
   }
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
      try {
         boolean unexpectedRollback = unexpected;

         try {
//          事務資源解綁
            triggerBeforeCompletion(status);

//          事務是否有回滾點
            if (status.hasSavepoint()) {
               if (status.isDebug()) {
                  logger.debug("Rolling back transaction to savepoint");
               }
//             事務狀態回退到回滾點
               status.rollbackToHeldSavepoint();
            }
            else if (status.isNewTransaction()) {
               if (status.isDebug()) {
                  logger.debug("Initiating transaction rollback");
               }
               doRollback(status);
            }
            else {
               // Participating in larger transaction參與更大的交易
               if (status.hasTransaction()) {
                  if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
                     if (status.isDebug()) {
                        logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
                     }
                     doSetRollbackOnly(status);
                  }
                  else {
                     if (status.isDebug()) {
                        logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
                     }
                  }
               }
               else {
                  logger.debug("Should roll back transaction but cannot - no transaction available");
               }
               // Unexpected rollback only matters here if we're asked to fail early若是咱們被要求提早失敗,那麼意外的回滾就很重要了。
               if (!isFailEarlyOnGlobalRollbackOnly()) {
                  unexpectedRollback = false;
               }
            }
         }
         catch (RuntimeException | Error ex) {
            triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
            throw ex;
         }

         triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);

         // Raise UnexpectedRollbackException if we had a global rollback-only marker若是咱們有一個僅用於全局回滾的標記,那麼就會引起unexpected tedrollbackexception
         if (unexpectedRollback) {
            throw new UnexpectedRollbackException(
                  "Transaction rolled back because it has been marked as rollback-only");
         }
      }
      finally {
         cleanupAfterCompletion(status);
      }
   }
         事務狀態回退到回滾點
               status.rollbackToHeldSavepoint();
public void rollbackToHeldSavepoint() throws TransactionException {
      Object savepoint = getSavepoint();
      if (savepoint == null) {
         throw new TransactionUsageException(
               "Cannot roll back to savepoint - no savepoint associated with current transaction");
      }
//    事務回滾到事務回滾點
      getSavepointManager().rollbackToSavepoint(savepoint);
//    釋放事務回滾點
      getSavepointManager().releaseSavepoint(savepoint);
      setSavepoint(null);
   }

返回到這個方法

org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback這行

   事務回滾
               doRollback(status);
@Override
   protected void doRollback(DefaultTransactionStatus status) {
//    獲取事務
      DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
//    獲取數據庫鏈接
      Connection con = txObject.getConnectionHolder().getConnection();
      if (status.isDebug()) {
         logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
      }
      try {
//       事務回滾
         con.rollback();
      }
      catch (SQLException ex) {
         throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
      }
   }

事務提交源碼解析

返回到這個方法org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowing這行

 

事務提交

txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());

進入到這個方法org.springframework.transaction.support.AbstractPlatformTransactionManager#commit

@Override
   public final void commit(TransactionStatus status) throws TransactionException {
      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;
//    若是是本地事務回滾
      if (defStatus.isLocalRollbackOnly()) {
         if (defStatus.isDebug()) {
            logger.debug("Transactional code has requested rollback");
         }
//       事務回滾
         processRollback(defStatus, false);
         return;
      }

//    全局事務回滾
      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;
      }

//    事務提交
      processCommit(defStatus);
   }
//     事務提交
      processCommit(defStatus);
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
      try {
         boolean beforeCompletionInvoked = false;

         try {
            boolean unexpectedRollback = false;
//          準備提交
            prepareForCommit(status);
//          出發提交以前回調
            triggerBeforeCommit(status);
            triggerBeforeCompletion(status);
            beforeCompletionInvoked = true;

            if (status.hasSavepoint()) {
               if (status.isDebug()) {
                  logger.debug("Releasing transaction savepoint");
               }
               unexpectedRollback = status.isGlobalRollbackOnly();
               status.releaseHeldSavepoint();
            }
            else if (status.isNewTransaction()) {
               if (status.isDebug()) {
                  logger.debug("Initiating transaction commit");
               }
               unexpectedRollback = status.isGlobalRollbackOnly();
//             事務提交
               doCommit(status);
            }
            else if (isFailEarlyOnGlobalRollbackOnly()) {
               unexpectedRollback = status.isGlobalRollbackOnly();
            }

            // Throw UnexpectedRollbackException if we have a global rollback-only若是咱們只進行全局回滾,那麼將拋出unexpected tedrollbackexception
            // marker but still didn't get a corresponding exception from commit.可是仍然沒有從commit獲得相應的異常。
            if (unexpectedRollback) {
               throw new UnexpectedRollbackException(
                     "Transaction silently rolled back because it has been marked as rollback-only");
            }
         }
         catch (UnexpectedRollbackException ex) {
            // can only be caused by doCommit只能由doCommit引發嗎
            triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
            throw ex;
         }
         catch (TransactionException ex) {
            // can only be caused by doCommit只能由doCommit引發嗎
            if (isRollbackOnCommitFailure()) {
               doRollbackOnCommitException(status, ex);
            }
            else {
               triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
            }
            throw ex;
         }
         catch (RuntimeException | Error ex) {
            if (!beforeCompletionInvoked) {
               triggerBeforeCompletion(status);
            }
            doRollbackOnCommitException(status, ex);
            throw ex;
         }

         // Trigger afterCommit callbacks, with an exception thrown there觸發afterCommit回調,並在其中拋出一個異常
         // propagated to callers but the transaction still considered as committed.傳播到調用者,但事務仍然被認爲是提交的。
         try {
            triggerAfterCommit(status);
         }
         finally {
            triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
         }

      }
      finally {
         cleanupAfterCompletion(status);
      }
   }

說到最後

本次解析僅表明我的看法,僅供參考。

相關文章
相關標籤/搜索