乐趣区

关于spring:聊聊TransactionSynchronization的invokeAfterCompletion

本文次要钻研一下 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

  • 聊聊 spring 的 TransactionSynchronizationAdapter
退出移动版