解读TransactionSynchronizationAdapter并封装对应工具类

写作原由:

工作中需要手工进行事务封装,故此不得不用到TransactionSynchronizationAdapter。故此看到项目中都是如下写法:

故此这边想进一步学习其原理和封装一个工具类:

概述:

TransactionSynchronizationAdapter 是 Spring 框架中的一个类,它实现了 TransactionSynchronization 接口,提供了一种方便的方式来使用事务同步回调。 通过实现 TransactionSynchronization 接口,开发者可以在事务的不同阶段(如提交前、提交后、回滚后等)执行自定义的逻辑。

原理:

TransactionSynchronizationManager 是 Spring 中管理事务同步的中心类。它维护了当前线程的事务同步回调,这些回调与当前线程绑定的资源(如数据库连接)相关联。

当一个事务被管理时,你可以通过 TransactionSynchronizationManager.registerSynchronization 方法注册一个 TransactionSynchronization 实例。Spring 会在事务的相应阶段调用该实例的回调方法。

TransactionSynchronizationAdapterTransactionSynchronization 的一个空实现,它为所有的方法提供了空操作。你可以选择性地覆盖你感兴趣的方法,而不是实现接口中的所有方法。

优点:

  1. 灵活性:允许在事务的关键阶段插入自定义逻辑,如资源清理、统计信息更新、后续操作触发等。
  2. 便利性 :通过提供默认实现,TransactionSynchronizationAdapter 使得你只需覆盖你关心的回调方法。
  3. 一致性:确保在事务的正确阶段执行操作,有助于保持代码的一致性和可维护性。
  4. 集成:与 Spring 的事务管理无缝集成,不需要额外的事务控制代码。

缺点:

  1. 依赖于Spring框架 :使用 TransactionSynchronizationAdapter 需要依赖于Spring框架,这对于非Spring项目来说可能是一个限制。
  2. 线程局限性TransactionSynchronization 是与线程绑定的,这意味着它只能在事务控制的同一线程中工作。
  3. 性能考虑:如果在事务同步回调中执行耗时操作,可能会影响事务的性能。
  4. 复杂性:在复杂的事务场景中,管理多个同步回调可能会增加代码的复杂性。

使用场景:

  • 在事务提交后发送消息或通知。
  • 在事务完成后执行某些统计或日志记录。
  • 在事务回滚后进行资源清理或状态重置。
  • 在事务提交前进行最后的校验或准备工作。

如何使用:

要使用 TransactionSynchronizationAdapter,你需要创建它的一个匿名类或子类,并覆盖你感兴趣的方法。然后,你可以在事务代码中注册这个同步适配器。下面是一个简单的例子,展示了如何在事务提交后执行一些自定义逻辑:

java 复制代码
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
 * @Author derek_smart
 * @Date 2024/5/31 10:01
 * @Description
 * <p> 简单示例
 */
public class MyService {

    public void performTransactionalOperation() {
        // 执行一些事务操作...

        // 注册事务同步适配器
        TransactionSynchronizationManager.registerSynchronization(
            new TransactionSynchronizationAdapter() {
                @Override
				   public void afterCommit() {
                    // 事务提交后执行的逻辑
                    doAfterTransactionCommit();
                }
            }
        );
    }

    private void doAfterTransactionCommit() {
        // 自定义逻辑...
    }
}

在这个例子中,afterCommit 方法被覆盖以实现特定的逻辑,这个逻辑将在事务成功提交后执行。你可以根据需要覆盖其他的方法。

请注意,为了使这个同步适配器工作,你的代码需要运行在 Spring 管理的事务环境中。如果你不在事务的上下文中使用 TransactionSynchronizationManager.registerSynchronization 方法,那么注册的同步适配器将不会被调用。

TransactionSynchronizationAdapter是 Spring 框架提供的一个便利类,它实现了TransactionSynchronization 接口。TransactionSynchronization 接口定义了一系列的回调方法,这些方法在事务的不同阶段被调用。TransactionSynchronizationAdapter` 为这些方法提供了默认的空实现,你可以通过继承这个类并覆盖特定的方法来实现自己的逻辑。### 核心方法:

以下是 TransactionSynchronization 接口中一些核心的回调方法,这些方法在 TransactionSynchronizationAdapter 中都有默认实现:

  • beforeCommit(boolean readOnly): 事务提交之前调用,readOnly 标志指示事务是否是只读的。
  • beforeCompletion(): 事务完成之前(即提交或回滚之前)调用。
  • afterCommit(): 事务提交之后调用。
  • afterCompletion(int status): 事务完成之后调用,status 表示完成状态(提交或回滚)。
  • suspend(): 事务挂起时调用。
  • resume(): 事务恢复时调用。
  • flush(): 清理挂起资源时调用。

流程图:

sequenceDiagram participant Client participant TransactionManager participant TransactionSynchronizationManager participant TransactionSynchronizationAdapter participant CustomLogic Client->>TransactionManager: Begin transaction TransactionManager->>TransactionSynchronizationManager: Register TransactionSynchronizationAdapter TransactionManager->>Client: Perform transactional work Client->>TransactionManager: Commit/Rollback transaction TransactionManager->>TransactionSynchronizationAdapter: Trigger beforeCommit (if committing) TransactionSynchronizationAdapter->>CustomLogic: Execute custom before commit logic TransactionManager->>TransactionSynchronizationAdapter: Trigger afterCommit (if committed) TransactionSynchronizationAdapter->>CustomLogic: Execute custom after commit logic TransactionManager->>TransactionSynchronizationAdapter: Trigger afterCompletion TransactionSynchronizationAdapter->>CustomLogic: Execute custom after completion logic (commit/rollback)

在流程图中,以下参与者:

  • Client: 调用事务管理器来开始和结束事务的客户端代码。
  • TransactionManager: 管理事务的边界,负责开始、提交或回滚事务。
  • TransactionSynchronizationManager: 管理事务同步回调的注册和触发。
  • TransactionSynchronizationAdapter: 提供默认实现,可以被覆盖以执行自定义逻辑。
  • CustomLogic: 自定义逻辑,可以在事务的特定阶段执行。

流程如下:

  1. 客户端代码请求事务管理器开始一个事务。
  2. 事务管理器在 TransactionSynchronizationManager 中注册 TransactionSynchronizationAdapter
  3. 客户端执行事务性工作。
  4. 事务完成后,客户端请求事务管理器提交或回滚事务。
  5. 如果是提交,TransactionSynchronizationAdapterbeforeCommit 方法将被触发。
  6. 客户端的自定义逻辑在提交前执行。
  7. 事务提交后,TransactionSynchronizationAdapterafterCommit 方法被触发。
  8. 客户端的自定义逻辑在提交后执行。
  9. 不论是提交还是回滚,TransactionSynchronizationAdapterafterCompletion 方法都会被触发。
  10. 客户端的自定义逻辑在事务完成后执行。

时序图:

sequenceDiagram autonumber participant Client as Client Code participant TransactionManager as Transaction Manager participant SynchronizationManager as TransactionSynchronizationManager participant SynchronizationAdapter as TransactionSynchronizationAdapter participant CustomLogic as Custom Logic Client->>+TransactionManager: Start transaction TransactionManager->>+SynchronizationManager: Register SynchronizationAdapter Client->>+TransactionManager: Perform transactional work TransactionManager->>-Client: Transactional work done Client->>+TransactionManager: Attempt commit alt Transaction commit TransactionManager->>+SynchronizationAdapter: beforeCommit() SynchronizationAdapter->>-CustomLogic: Execute before commit logic TransactionManager->>+SynchronizationAdapter: afterCommit() SynchronizationAdapter->>-CustomLogic: Execute after commit logic else Transaction rollback TransactionManager->>+SynchronizationAdapter: beforeCompletion() SynchronizationAdapter->>-CustomLogic: Execute before completion logic end TransactionManager->>+SynchronizationAdapter: afterCompletion(status) SynchronizationAdapter->>-CustomLogic: Execute after completion logic TransactionManager->>-Client: Transaction ended

在时序图中,以下步骤:

  1. 客户端代码请求事务管理器开始一个新事务。
  2. 事务管理器向 TransactionSynchronizationManager 注册 TransactionSynchronizationAdapter
  3. 客户端执行事务性工作。
  4. 事务性工作完成后,客户端请求提交事务。
  5. 如果事务提交,事务管理器将调用 TransactionSynchronizationAdapterbeforeCommit() 方法,然后是 afterCommit() 方法。
  6. 如果事务回滚,事务管理器将调用 TransactionSynchronizationAdapterbeforeCompletion() 方法。
  7. 无论事务提交还是回滚,事务管理器都会调用 TransactionSynchronizationAdapterafterCompletion(status) 方法。
  8. 客户端代码接收到事务结束的通知。

TransactionSynchronizationAdapter 的每个方法中,可以执行自定义逻辑,如在提交前验证数据,在提交后发送通知,或在事务完成后清理资源。

封装工具类:

typescript 复制代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.reactive.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
/**
 * @Author derek_smart
 * @Date 2024/5/31 10:10
 * @Description
 * <p> TransactionSynchronizationAdapter 工具类
 */
@Slf4j
public class TransactionManageService {

    private static ExecutorService defaultExecutorService = Executors.newCachedThreadPool();

    public static <T> void afterCommitDefault(T args, Consumer<? super T> consumer) {
        afterCommit(args, consumer, defaultExecutorService);
    }

    public static void setDefaultExecutorService(ExecutorService executorService) {
        defaultExecutorService = executorService;
    }

    /**
     * 添加钩子来跟踪异步操作的性能。
     * @param args
     * @param consumer
     * @param executorService
     * @param <T>
     */
    public static <T> void afterCommit(T args, Consumer<? super T> consumer, ExecutorService executorService) {
        Objects.requireNonNull(consumer, "Consumer must not be null");
        Objects.requireNonNull(executorService, "ExecutorService must not be null");
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                                                                      @Override
                                                                      public void afterCommit() {
                                                                          executorService.submit(() -> {
                                                                              long startTime = System.currentTimeMillis();
                                                                              try {
                                                                                  consumer.accept(args);
                                                                              } catch (Exception e) {
                                                                                  log.error("Error executing afterCommit", e);
                                                                              } finally {
                                                                                  long duration = System.currentTimeMillis() - startTime;
                                                                                  log.info("afterCommit executed in {} ms", duration);
                                                                              }
                                                                          });
                                                                      }
                                                                  }
        );
    }

    /**
     *
     * @param args
     * @param consumer
     * @param executorService
     * @param errorMsg
     * @param <T>
     */
    public static <T> void afterCommit(T args, Consumer<? super T> consumer, ExecutorService executorService, String errorMsg) {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                                                                      @Override
                                                                      public void afterCommit() {
                                                                          executorService.submit(() -> {
                                                                              try {
                                                                                  consumer.accept(args);
                                                                              } catch (Exception e) {
                                                                                  log.error(errorMsg, e);
                                                                              }
                                                                          });
                                                                      }
                                                                  }
        );
    }

    /**
     *
     * @param args
     * @param consumer
     * @param <T>
     */
    public static <T> void afterCommit(T args, Consumer<? super T> consumer) {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                                                                      @Override
                                                                      public void afterCommit() {
                                                                          consumer.accept(args);
                                                                      }
                                                                  }
        );
    }

    /**
     *
     * @param runnable
     * @param executorService
     * @param <T>
     */
    public static <T> void afterCommit(Runnable runnable, ExecutorService executorService) {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                                                                      @Override
                                                                      public void afterCommit() {
                                                                          executorService.submit(() -> {
                                                                              try {
                                                                                  runnable.run();
                                                                              } catch (Exception e) {
                                                                                  log.error("run fail", e);
                                                                              }
                                                                          });
                                                                      }
                                                                  }
        );
    }

    /**
     * 增加事务回滚后的操作支持
     *
     * @param args
     * @param consumer
     * @param <T>
     */
    public static <T> void afterRollback(T args, Consumer<? super T> consumer) {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCompletion(int status) {
                if (status == TransactionSynchronization.STATUS_ROLLED_BACK) {
                    consumer.accept(args);
                }
            }
        });
    }

    // 在事务提交后执行给定的操作
    public static void afterCommit(Runnable action) {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                action.run();
            }
        });
    }

    // 在事务回滚后执行给定的操作
    public static void afterRollback(Runnable action) {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCompletion(int status) {
                if (status == TransactionSynchronization.STATUS_ROLLED_BACK) {
                    action.run();
                }
            }
        });
    }

    // 在事务提交后执行给定的操作,并消费事务结果
    public static <T> void afterCommit(Consumer<T> action, T result) {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                action.accept(result);
            }
        });
    }

    // 在事务回滚后执行给定的操作,并消费事务结果
    public static <T> void afterRollback(Consumer<T> action, T result) {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCompletion(int status) {
                if (status == TransactionSynchronization.STATUS_ROLLED_BACK) {
                    action.accept(result);
                }
            }
        });
    }

}

使用这个工具类的例子:

java 复制代码
import org.springframework.stereotype.Service;  
import org.springframework.transaction.annotation.Transactional;  
  
@Service  
public class MyTransactionalService {  
  
    @Transactional  
    public void executeWithTransaction() {  
        // 执行一些事务操作...  
  
        // 注册事务提交后的操作  
        TransactionUtils.afterCommit(() -> System.out.println("Transaction committed successfully!"));  
  
        // 注册事务回滚后的操作  
        TransactionUtils.afterRollback(() -> System.out.println("Transaction rolledback!"));  
    }  
}  

以上类为自己总结写,由时间原因故此不再详细介绍如何使用,后续有空继续。

总结:

总之,TransactionSynchronizationAdapter 提供了一种强大的机制来扩展 Spring 事务的行为。当使用得当时,它可以增强应用程序的事务管理能力,但也需要注意其带来的依赖和潜在的性能影响。

相关推荐
计算机-秋大田1 分钟前
基于Spring Boot的船舶监造系统的设计与实现,LW+源码+讲解
java·论文阅读·spring boot·后端·vue
神里大人2 分钟前
idea、pycharm等软件的文件名红色怎么变绿色
java·pycharm·intellij-idea
小冉在学习20 分钟前
day53 图论章节刷题Part05(并查集理论基础、寻找存在的路径)
java·算法·图论
CXDNW41 分钟前
【网络面试篇】HTTP(2)(笔记)——http、https、http1.1、http2.0
网络·笔记·http·面试·https·http2.0
嚣张农民1 小时前
JavaScript中Promise分别有哪些函数?
前端·javascript·面试
代码之光_19801 小时前
保障性住房管理:SpringBoot技术优势分析
java·spring boot·后端
ajsbxi1 小时前
苍穹外卖学习记录
java·笔记·后端·学习·nginx·spring·servlet
StayInLove1 小时前
G1垃圾回收器日志详解
java·开发语言
对许1 小时前
SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder“
java·log4j
鹿屿二向箔2 小时前
基于SSM(Spring + Spring MVC + MyBatis)框架的咖啡馆管理系统
spring·mvc·mybatis