TransactionSynchronizationManagerTransaction synchronization manager

TransactionSynchronizationManagerunderstand

TransactionSynchronizationManager using multiple ThreadLocal maintenance each thread affairs independent resource information, cooperate with AbstractPlatformTransactionManager and its subclasses, Setting thread transaction configuration properties and running state, and can be achieved through the custom TransactionSynchronization register, to monitor the operation of the transaction For the business scenario: Suppose there is an asynchronous operation at the end of the business process, and the business process depends on the transaction, and the asynchronous operation depends on the data that the business process adds or updates in the transaction. The problem is that the asynchronous operation is executed before the transaction is committed, and the data queried is before the transaction is committed. Asynchronous operation is invalid You can use Spring’s custom TransactionSynchronization TransactionSynchronizationManager registration, realize afterCommit method (there are other methods), Enables custom business logic to be executed in that running state of the transaction

TransactionSynchronizationManagerThe source code

public abstract class TransactionSynchronizationManager {
    // Thread context holds the thread pool object: ConnectionHolder Map object. Threads can obtain the same Connection object through this property.
	private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal<>("Transactional resources");
    // Transaction synchronizer, the extension code of the transaction runtime, each thread can register N transaction synchronizers.
	private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations = new NamedThreadLocal<>("Transaction synchronizations");
    // Transaction name
	private static final ThreadLocal<String> currentTransactionName = new NamedThreadLocal<>("Current transaction name");
    // Whether the transaction is read-only
	private static final ThreadLocal<Boolean> currentTransactionReadOnly = new NamedThreadLocal<>("Current transaction read-only status");
    // Transaction isolation level
	private static final ThreadLocal<Integer> currentTransactionIsolationLevel = new NamedThreadLocal<>("Current transaction isolation level");
    // Whether the transaction is enabled
	private static final ThreadLocal<Boolean> actualTransactionActive = new NamedThreadLocal<>("Actual transaction active");

}
Copy the code

In the org. Springframework. Transaction. The interceptor. TransactionInterceptor# invoke, to intercept the transaction method. In createTransactionIfNecessary when performing getTransaction invokes AbstractPlatformTransactionManager# prepareSynchronization synchronizer method to initialize the affairs.

/** * Initialize transaction synchronization as appropriate. */
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
	if(status.isNewSynchronization()) { TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());  TransactionSynchronizationManager.setCurrentTransactionIsolationLevel( definition.getIsolationLevel() ! = TransactionDefinition.ISOLATION_DEFAULT ? definition.getIsolationLevel() :null); TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly()); TransactionSynchronizationManager.setCurrentTransactionName(definition.getName()); TransactionSynchronizationManager.initSynchronization(); }}Copy the code

TransactionSynchronizationextension

Generally used is TransactionSynchronization afterCommit and afterCompletion method

TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
    @Override
    public void afterCommit(a) {
        // Customize business operations}});Copy the code

Where do afterCommit and afterCompletion trigger?

In AbstractPlatformTransactionManager processCommit method all TransactionSynchronization callback

private void processCommit(DefaultTransactionStatus status) throws TransactionException {
    try {
        // Commit the transactiondoCommit(status); .try {
           // Call back afterCommit methods for all transaction synchronizers.
           triggerAfterCommit(status);
        }
        finally {
           // Callback afterCompletion methods for all transaction synchronizers.triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED); }}finally {
        / / remove TransactionSynchronizationManager ThreadLocal data binding.
        // Unbind resources from Thread.
        // Set Commit to auto Commit.
        // Clean up the ConnectionHolder resource.cleanupAfterCompletion(status); }}Copy the code