TransactionSynchronizationAdapter結合ThreadPoolExecutor實現事務後處理功能

         項目中有一個功能涉及多個業務流程,且在同一個事務中,每個業務流程結束後都需要進行RPC調用,考慮到RPC調用的代價,決定做成異步調用,但是由於每個調用都必須在業務流程結束後進行,這時候就想到TransactionSynchronizationManager和TransactionSynchronizationAdapter。

         TransactionSynchronizationManager這個類中由一系列的ThreadLocal ,我們需要關注的是synchronizations,在後面使用到的TransactionSynchronizationManager.isSynchronizationActive()、TransactionSynchronizationManager.registerSynchronization()和new TransactionSynchronizationAdapter(),都與它密切有關。

        在Spring在開啓數據庫事務(無論是使用@Transactional註解,還是用xml配置)時,都會向其中寫入一個實例,用於自動處理Connection的獲取、提交或回滾等操作。

       再看isSynchronizationActive()方法,判斷了synchronizations中是否有數據(Set<TransactionSynchronization>非null即可,並不要求其中有TransactionSynchronization實例。

       再看registerSynchronization()方法,首先調用isSynchronizationActive()做一個校驗;然後將入參synchronization添加到synchronizations 中。入參synchronization中的方法不會在這裏執行,而是要等到事務執行到特定階段時纔會被調用。

         TransactionSynchronizationAdapter是一個適配器:它實現了TransactionSynchronization接口,併爲每一個接口方法提供了一個空的實現。這類適配器的基本思想是:接口中定義了很多方法,然而業務代碼往往只需要實現其中一小部分。利用這種“空實現”適配器,我們可以專注於業務上需要處理的回調方法,而不用在業務類中放大量而且重複的空方法。

         結合TransactionSynchronizationManager和TransactionSynchronizationAdapter利用ThreadPoolExecutor實現一個事務後多線程處理功能。

package com.*.module.spring.support;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * 事務提交異步線程
 *
 * @author ly
 */
public class TransactionAfterCommitExecutor extends ThreadPoolExecutor {

    private static final Logger LOGGER = LoggerFactory.getLogger(TransactionAfterCommitExecutor.class);


    public TransactionAfterCommitExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    public TransactionAfterCommitExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
    }

    public TransactionAfterCommitExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
    }

    public TransactionAfterCommitExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    }


    private ThreadLocal<List<Runnable>> currentRunables = new ThreadLocal<List<Runnable>>(){
        @Override
        protected List<Runnable> initialValue() {
            return new ArrayList<>(5);
        }
    };

    private ThreadLocal<Boolean> registed = new ThreadLocal<Boolean>(){
        @Override
        protected Boolean initialValue() {
            return false;
        }
    };

    /**
     * 默認策略丟棄最老的數據
     */
    public TransactionAfterCommitExecutor() {
        this(
                50, 500,
                500L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(1024),
                new ThreadFactoryBuilder().setNameFormat("transaction-after-commit-call-pool-%d").build(),
                new ThreadPoolExecutor.DiscardOldestPolicy());
    }

    @Override
    public void execute(final Runnable runnable) {
        //如果事務同步未啓用則認爲事務已經提交,馬上進行異步處理
        if (!TransactionSynchronizationManager.isSynchronizationActive()) {
            super.execute(runnable);
        } else {
            //同一個事務的合併到一起處理
            currentRunables.get().add(runnable);
            //如果存在事務則在事務結束後異步處理
            if(!registed.get()){
                TransactionSynchronizationManager.registerSynchronization(new AfterCommitTransactionSynchronizationAdapter());
                registed.set(true);
            }
        }
    }

    @Override
    public Future<?> submit(final Runnable runnable) {
        //如果事務同步未啓用則認爲事務已經提交,馬上進行異步處理
        if (!TransactionSynchronizationManager.isSynchronizationActive()) {
            return super.submit(runnable);
        } else {
            final RunnableFuture<Void> ftask = newTaskFor(runnable, null);
            //如果存在事務則在事務結束後異步處理
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    TransactionAfterCommitExecutor.super.submit(ftask);
                }
            });
            return ftask;
        }
    }

    private class AfterCommitTransactionSynchronizationAdapter extends TransactionSynchronizationAdapter{
        @Override
        public void afterCompletion(int status) {
            final List<Runnable> txRunables = new ArrayList<>(currentRunables.get());
            currentRunables.remove();
            registed.remove();
            if(status == STATUS_COMMITTED){
                TransactionAfterCommitExecutor.super.execute(new Runnable() {
                    @Override
                    public void run() {
                        for (Runnable runnable : txRunables) {
                            try {
                                runnable.run();
                            } catch (Exception e) {
                                LOGGER.error("ex:",e);
                            }
                        }
                    }
                });
            }
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章