privatestaticfinal ThreadLocal<Set<TransactionSynchronization>> synchronizations = new NamedThreadLocal<Set<TransactionSynchronization>>("Transaction synchronizations");
/** * Register a new transaction synchronization for the current thread. * Typically called by resource management code. * <p>Note that synchronizations can implement the * {@link org.springframework.core.Ordered} interface. * They will be executed in an order according to their order value (if any). * @param synchronization the synchronization object to register * @throws IllegalStateException if transaction synchronization is not active * @see org.springframework.core.Ordered */ publicstaticvoidregisterSynchronization(TransactionSynchronization synchronization) throws IllegalStateException {
Assert.notNull(synchronization, "TransactionSynchronization must not be null"); if (!isSynchronizationActive()) { thrownew IllegalStateException("Transaction synchronization is not active"); } synchronizations.get().add(synchronization); }
/** * Return an unmodifiable snapshot list of all registered synchronizations * for the current thread. * @return unmodifiable List of TransactionSynchronization instances * @throws IllegalStateException if synchronization is not active * @see TransactionSynchronization */ publicstatic List<TransactionSynchronization> getSynchronizations()throws IllegalStateException { Set<TransactionSynchronization> synchs = synchronizations.get(); if (synchs == null) { thrownew IllegalStateException("Transaction synchronization is not active"); } // Return unmodifiable snapshot, to avoid ConcurrentModificationExceptions // while iterating and invoking synchronization callbacks that in turn // might register further synchronizations. if (synchs.isEmpty()) { return Collections.emptyList(); } else { // Sort lazily here, not in registerSynchronization. List<TransactionSynchronization> sortedSynchs = new ArrayList<TransactionSynchronization>(synchs); AnnotationAwareOrderComparator.sort(sortedSynchs); return Collections.unmodifiableList(sortedSynchs); } }
/** * Actually invoke the {@code afterCommit} methods of the * given Spring TransactionSynchronization objects. * @param synchronizations List of TransactionSynchronization objects * @see TransactionSynchronization#afterCommit() */ publicstaticvoidinvokeAfterCommit(List<TransactionSynchronization> synchronizations){ if (synchronizations != null) { for (TransactionSynchronization synchronization : synchronizations) { synchronization.afterCommit(); } } }
/** * Process an actual commit. * Rollback-only flags have already been checked and applied. * @param status object representing the transaction * @throws TransactionException in case of commit failure */ privatevoidprocessCommit(DefaultTransactionStatus status)throws TransactionException { try { boolean beforeCompletionInvoked = false; try { prepareForCommit(status); triggerBeforeCommit(status); triggerBeforeCompletion(status); beforeCompletionInvoked = true; boolean globalRollbackOnly = false; if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) { globalRollbackOnly = status.isGlobalRollbackOnly(); } if (status.hasSavepoint()) { if (status.isDebug()) { logger.debug("Releasing transaction savepoint"); } status.releaseHeldSavepoint(); } elseif (status.isNewTransaction()) { if (status.isDebug()) { logger.debug("Initiating transaction commit"); } doCommit(status); } // Throw UnexpectedRollbackException if we have a global rollback-only // marker but still didn't get a corresponding exception from commit. if (globalRollbackOnly) { thrownew UnexpectedRollbackException( "Transaction silently rolled back because it has been marked as rollback-only"); } } catch (UnexpectedRollbackException ex) { // can only be caused by doCommit triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK); throw ex; } catch (TransactionException ex) { // can only be caused by doCommit if (isRollbackOnCommitFailure()) { doRollbackOnCommitException(status, ex); } else { triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN); } throw ex; } catch (RuntimeException ex) { if (!beforeCompletionInvoked) { triggerBeforeCompletion(status); } doRollbackOnCommitException(status, ex); throw ex; } catch (Error err) { if (!beforeCompletionInvoked) { triggerBeforeCompletion(status); } doRollbackOnCommitException(status, err); throw err; }
// Trigger afterCommit callbacks, with an exception thrown there // propagated to callers but the transaction still considered as committed. try { // 事务执行后 triggerAfterCommit(status); } finally { triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED); }
/** * Return if a new transaction synchronization has been opened * for this transaction. */ publicbooleanisNewSynchronization(){ returnthis.newSynchronization; }
/** * Trigger {@code afterCommit} callbacks. * @param status object representing the transaction */ privatevoidtriggerAfterCommit(DefaultTransactionStatus status){ if (status.isNewSynchronization()) { if (status.isDebug()) { logger.trace("Triggering afterCommit synchronization"); } TransactionSynchronizationUtils.triggerAfterCommit(); } }
/** * Return if transaction synchronization is active for the current thread. * Can be called before register to avoid unnecessary instance creation. * @see #registerSynchronization */ publicstaticbooleanisSynchronizationActive(){ return (synchronizations.get() != null); }