Springboot在事务提交后回调执行代码-TransactionSynchronization

在开发过程中大家一定遇到过一种业务场景,需要在事务执行结束后再执行的代码逻辑,这个代码不受事务成败与否的影响,spring也为我们提供了这种功能那就是TransactionSynchronization。

为了方便使用我们直接封装成一个工具类,使用ThreadLoal对方法与线程进行绑定。

package com.casa.leetcode.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.LinkedList;
import java.util.List;
import java.util.Optional;


/**
 * 用于处理一些必须要等待事务提交后执行的操作
 *
 * save操作整个流程链
 * - 2022-08-16 10:04:15,586 [http-nio-8089-exec-1] ERROR c.c.l.u.TransactionLifeCycleUtils - TransactionLifeCycleUtils --- beforeCommit
 * - 2022-08-16 10:04:15,586 [http-nio-8089-exec-1] ERROR c.c.l.u.TransactionLifeCycleUtils - TransactionLifeCycleUtils --- beforeCompletion
 * - 2022-08-16 10:04:15,648 [http-nio-8089-exec-1] ERROR c.c.l.u.TransactionLifeCycleUtils - TransactionLifeCycleUtils --- afterCommit
 * - 2022-08-16 10:04:15,648 [http-nio-8089-exec-1] ERROR c.c.l.u.TransactionLifeCycleUtils - TransactionLifeCycleUtils --- afterCompletion --- 0
 *
 */
@Slf4j
public class TransactionLifeCycleUtils {


    private static ThreadLocal> threadLocalRunnableList = new ThreadLocal<>();

    private static TransactionSynchronization action = new TransactionSynchronization() {
        @Override
        public void afterCompletion(int status) {
            if (status == STATUS_COMMITTED) {
                List runnableList = threadLocalRunnableList.get();
                threadLocalRunnableList.remove();
                runnableList.forEach(Runnable::run);
            }
            TransactionSynchronization.super.afterCompletion(status);
        }
    };


    /**
     * 单例
     * @param command
     */
    public static void afterCommitSuccessCallback(Runnable command) {
        ThreadLocal> local = threadLocalRunnableList;

        Optional.ofNullable(local.get()).ifPresentOrElse(
                list -> list.add(command),
                () -> {
                    LinkedList list = new LinkedList<>();
                    list.add(command);
                    local.set(list);
                    TransactionSynchronizationManager.registerSynchronization(action);
                }
        );

    }


}

那我们如何使用呢

@Transactional
public Object save(SystemConfig config){
        TransactionLifeCycleUtils.afterCommitSuccessCallback(
            () -> log.info("save jpa success.")
        );
        return repository.saveAndFlush(config);
 }

再说说如果不使用TransactionSynchronization我们想在事务之外执行代码是怎么实现的。

public void saveConfig(SystemConfig config){
        this.save(config);
        //事务之外的逻辑
        log.info("save jpa success.")
}
@Transactional
public Object save(SystemConfig config){
        return repository.saveAndFlush(config);
 }

有问题欢迎讨论i❣

你可能感兴趣的:(Springboot在事务提交后回调执行代码-TransactionSynchronization)