美文网首页
聊聊TransactionSynchronization的inv

聊聊TransactionSynchronization的inv

作者: go4it | 来源:发表于2023-09-09 14:59 被阅读0次

    本文主要研究一下TransactionSynchronization的invokeAfterCompletion

    afterCompletion

    org/springframework/transaction/support/TransactionSynchronization.java

    public interface TransactionSynchronization extends Flushable {
    
        /** Completion status in case of proper commit. */
        int STATUS_COMMITTED = 0;
    
        /** Completion status in case of proper rollback. */
        int STATUS_ROLLED_BACK = 1;
    
        /** Completion status in case of heuristic mixed completion or system errors. */
        int STATUS_UNKNOWN = 2;
    
        //......
    
        /**
         * Invoked after transaction commit. Can perform further operations right
         * <i>after</i> the main transaction has <i>successfully</i> committed.
         * <p>Can e.g. commit further operations that are supposed to follow on a successful
         * commit of the main transaction, like confirmation messages or emails.
         * <p><b>NOTE:</b> The transaction will have been committed already, but the
         * transactional resources might still be active and accessible. As a consequence,
         * any data access code triggered at this point will still "participate" in the
         * original transaction, allowing to perform some cleanup (with no commit following
         * anymore!), unless it explicitly declares that it needs to run in a separate
         * transaction. Hence: <b>Use {@code PROPAGATION_REQUIRES_NEW} for any
         * transactional operation that is called from here.</b>
         * @throws RuntimeException in case of errors; will be <b>propagated to the caller</b>
         * (note: do not throw TransactionException subclasses here!)
         */
        default void afterCommit() {
        }
    
        /**
         * Invoked after transaction commit/rollback.
         * Can perform resource cleanup <i>after</i> transaction completion.
         * <p><b>NOTE:</b> The transaction will have been committed or rolled back already,
         * but the transactional resources might still be active and accessible. As a
         * consequence, any data access code triggered at this point will still "participate"
         * in the original transaction, allowing to perform some cleanup (with no commit
         * following anymore!), unless it explicitly declares that it needs to run in a
         * separate transaction. Hence: <b>Use {@code PROPAGATION_REQUIRES_NEW}
         * for any transactional operation that is called from here.</b>
         * @param status completion status according to the {@code STATUS_*} constants
         * @throws RuntimeException in case of errors; will be <b>logged but not propagated</b>
         * (note: do not throw TransactionException subclasses here!)
         * @see #STATUS_COMMITTED
         * @see #STATUS_ROLLED_BACK
         * @see #STATUS_UNKNOWN
         * @see #beforeCompletion
         */
        default void afterCompletion(int status) {
        }
    
    }
    

    afterCompletion方法有入参status,表示事务结束时候的状态,0表示事务已提交,1表示事务已回滚,2表示事务未知;与afterCommit的一个最重要的区别是afterCompletion的异常会被捕获,不像afterCommit会抛给调用方

    invokeAfterCompletion

    org/springframework/transaction/support/TransactionSynchronizationUtils.java

        /**
         * Actually invoke the {@code afterCompletion} methods of the
         * given Spring TransactionSynchronization objects.
         * @param synchronizations a List of TransactionSynchronization objects
         * @param completionStatus the completion status according to the
         * constants in the TransactionSynchronization interface
         * @see TransactionSynchronization#afterCompletion(int)
         * @see TransactionSynchronization#STATUS_COMMITTED
         * @see TransactionSynchronization#STATUS_ROLLED_BACK
         * @see TransactionSynchronization#STATUS_UNKNOWN
         */
        public static void invokeAfterCompletion(@Nullable List<TransactionSynchronization> synchronizations,
                int completionStatus) {
    
            if (synchronizations != null) {
                for (TransactionSynchronization synchronization : synchronizations) {
                    try {
                        synchronization.afterCompletion(completionStatus);
                    }
                    catch (Throwable tsex) {
                        logger.error("TransactionSynchronization.afterCompletion threw exception", tsex);
                    }
                }
            }
        }
    

    可以看到TransactionSynchronizationUtils的invokeAfterCompletion方法会遍历synchronizations,挨个执行afterCompletion,注意这里catch了Throwable异常,进行了error级别的log

    AbstractPlatformTransactionManager

    org/springframework/transaction/support/AbstractPlatformTransactionManager.java

        /**
         * Actually invoke the {@code afterCompletion} methods of the
         * given Spring TransactionSynchronization objects.
         * <p>To be called by this abstract manager itself, or by special implementations
         * of the {@code registerAfterCompletionWithExistingTransaction} callback.
         * @param synchronizations a List of TransactionSynchronization objects
         * @param completionStatus the completion status according to the
         * constants in the TransactionSynchronization interface
         * @see #registerAfterCompletionWithExistingTransaction(Object, java.util.List)
         * @see TransactionSynchronization#STATUS_COMMITTED
         * @see TransactionSynchronization#STATUS_ROLLED_BACK
         * @see TransactionSynchronization#STATUS_UNKNOWN
         */
        protected final void invokeAfterCompletion(List<TransactionSynchronization> synchronizations, int completionStatus) {
            TransactionSynchronizationUtils.invokeAfterCompletion(synchronizations, completionStatus);
        }
    
        /**
         * Trigger {@code afterCompletion} callbacks.
         * @param status object representing the transaction
         * @param completionStatus completion status according to TransactionSynchronization constants
         */
        private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus) {
            if (status.isNewSynchronization()) {
                List<TransactionSynchronization> synchronizations = TransactionSynchronizationManager.getSynchronizations();
                TransactionSynchronizationManager.clearSynchronization();
                if (!status.hasTransaction() || status.isNewTransaction()) {
                    if (status.isDebug()) {
                        logger.trace("Triggering afterCompletion synchronization");
                    }
                    // No transaction or new transaction for the current scope ->
                    // invoke the afterCompletion callbacks immediately
                    invokeAfterCompletion(synchronizations, completionStatus);
                }
                else if (!synchronizations.isEmpty()) {
                    // Existing transaction that we participate in, controlled outside
                    // of the scope of this Spring transaction manager -> try to register
                    // an afterCompletion callback with the existing (JTA) transaction.
                    registerAfterCompletionWithExistingTransaction(status.getTransaction(), synchronizations);
                }
            }
        }
    

    AbstractPlatformTransactionManager的invokeAfterCompletion委托给了TransactionSynchronizationUtils.invokeAfterCompletion;triggerAfterCompletion主要是根据事务状态执行不同逻辑,分别是invokeAfterCompletion与registerAfterCompletionWithExistingTransaction,后者主要是JTA之类的场景,它回传的status是STATUS_UNKNOWN

    小结

    afterCompletion方法有入参status,表示事务结束时候的状态,0表示事务已提交,1表示事务已回滚,2表示事务未知(一般是JTA相关);与afterCommit的一个最重要的区别是afterCompletion的异常(Throwable)会被捕获,不像afterCommit会抛给调用方

    doc

    相关文章

      网友评论

          本文标题:聊聊TransactionSynchronization的inv

          本文链接:https://www.haomeiwen.com/subject/tuljvdtx.html