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