本文主要研究一下TransactionSynchronization的invokeAfterCompletion
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
* after the main transaction has successfully committed.
* Can e.g. commit further operations that are supposed to follow on a successful
* commit of the main transaction, like confirmation messages or emails.
*
NOTE: 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: Use {@code PROPAGATION_REQUIRES_NEW} for any
* transactional operation that is called from here.
* @throws RuntimeException in case of errors; will be propagated to the caller
* (note: do not throw TransactionException subclasses here!)
*/
default void afterCommit() {
}
/**
* Invoked after transaction commit/rollback.
* Can perform resource cleanup after transaction completion.
*
NOTE: 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: Use {@code PROPAGATION_REQUIRES_NEW}
* for any transactional operation that is called from here.
* @param status completion status according to the {@code STATUS_*} constants
* @throws RuntimeException in case of errors; will be logged but not propagated
* (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会抛给调用方
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 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
org/springframework/transaction/support/AbstractPlatformTransactionManager.java
/**
* Actually invoke the {@code afterCompletion} methods of the
* given Spring TransactionSynchronization objects.
* 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 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 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会抛给调用方