Spring中TransactionSynchronizationManager的使用详解

 更新时间:2023年09月19日 09:00:12   作者:韩_师兄  
这篇文章主要介绍了Spring中TransactionSynchronizationManager的使用详解,TransactionSynchronizationManager是事务同步管理器,监听事务的操作,来实现在事务前后可以添加一些指定操作,需要的朋友可以参考下

1 概述

TransactionSynchronizationManager : 事务同步管理器,监听事务的操作,来实现在事务前后可以添加一些指定操作

在遇到一些场景, 如上一步保存的数据, 在接下来的异步处理的业务中有使用,但是因为保存数据过程中,可能出现异常,导致数据回滚,那么后续的业务操作也需要放弃. 对于上述业务场景, 可以使用TransactionSynchronizationManager解决问题

查看一下 TransactionSynchronizationManager 类 :

public abstract class TransactionSynchronizationManager {
	private static final Log logger = LogFactory.getLog(TransactionSynchronizationManager.class);
	private static final ThreadLocal<Map<Object, Object>> resources =
			new NamedThreadLocal<>("Transactional resources");
	private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
			new NamedThreadLocal<>("Transaction synchronizations");
	private static final ThreadLocal<String> currentTransactionName =
			new NamedThreadLocal<>("Current transaction name");
	private static final ThreadLocal<Boolean> currentTransactionReadOnly =
			new NamedThreadLocal<>("Current transaction read-only status");
	private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
			new NamedThreadLocal<>("Current transaction isolation level");
	private static final ThreadLocal<Boolean> actualTransactionActive =
			new NamedThreadLocal<>("Actual transaction active");
    // ...
}

参数说明:

  • resources 保存连接资源, 一个方法里面可能包含两个事务(比如事务传播特性为:TransactionDefinition#PROPAGATION_REQUIRES_NEW),所以就用 Map 来保存资源.
  • synchronizations 线程同步器,对 Spring 事务的扩展. 在Spring中通过@Transactional注解,在方法上,这个方法就有事务特性.
  • currentTransactionReadOnly 保存当前事务是否只读
  • currentTransactionName 保存当前事务名称,默认为空
  • currentTransactionIsolationLevel 保存当前事务的隔离级别
  • actualTransactionActive 保存当前事务是否还处于Active活跃状态

2 案例

以常见的用户注册,然后发送激活码为例.

    public void save(){
        // 保存用户
        saveUser();
        // 发送消息 异步执行
        executorService.execute(() -> sendMessage());
    }

说明:

在用户注册操作, 会将用户信息报错,可能会调一些其他模块,如积分模块等等, 进行数据库报错操作.会进行数据回滚, 但是异步操作,此时不能再进行回滚了.

所以我们需要等保存数据的事务,已经完成提交,再执行异步操作.

改造:

    public void save(){
        // 保存用户
        saveUser();
        // 判断当前线程是否存在活跃状态的事务
        boolean actualTransactionActive = TransactionSynchronizationManager.isActualTransactionActive();
        // 不存在则事务都完成
        if (!actualTransactionActive){
            // 异步操作 发送消息
            executorService.execute(() -> sendMessage());
        }else{
            // 存在活跃事务, 则监听事务, afterCommit是指事务提交完再执行
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                   // 异步操作 发送消息
                    executorService.execute(() -> sendMessage());
                }
            });
        }
}

通过TransactionSynchronizationManager,保证当前线程的事务都提交完成后,再进行异步的消息发送,解决了上述的问题. 避免出现数据未保存,而发送激活码或提示信息等.

查看一下 TransactionSynchronizationAdapter 类

public abstract class TransactionSynchronizationAdapter implements TransactionSynchronization, Ordered {
	@Override
	public int getOrder() {
		return Ordered.LOWEST_PRECEDENCE;
	}
    // 暂停此同步 应该从事务同步管理器中解绑资源
	@Override
	public void suspend() {
	}
    //  恢复此同步。 应该将资源重新绑定到 TransactionSynchronizationManager
	@Override
	public void resume() {
	}
    // 将基础会话刷新到数据存储
	@Override
	public void flush() {
	}
    // 在事务提交之前调用(在完成之前之前)顺序倒数第四
	@Override
	public void beforeCommit(boolean readOnly) {
	}
    // 在事务提交/回滚之前调用。顺序倒数第三
	@Override
	public void beforeCompletion() {
	}
    // 在事务提交后调用  顺序倒数第二
	@Override
	public void afterCommit() {
	}
    // 在事务提交/回滚后调用 可以进行资源清理 顺序倒数第一
	@Override
	public void afterCompletion(int status) {
	}
}

根据上述类方法含义,通常业务选择使用afterCommit进行重写,执行异步业务操作.

3 总结

在上述问题已经场景, 之前有遇到过几次, 都是采用了其他方法解决, 那些方法或多或少都有一些问题,如甚至使用过编程式事务去进行二次控制.而使用TransactionSynchronizationManager, 则是很符合这个业务场景的需求.

到此这篇关于Spring中TransactionSynchronizationManager的使用详解的文章就介绍到这了,更多相关TransactionSynchronizationManager的使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Springboot使用ResponseBody汉字返回问号问题

    Springboot使用ResponseBody汉字返回问号问题

    这篇文章主要介绍了Springboot使用ResponseBody汉字返回问号问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • 浅析对Java关键字final和static的理解

    浅析对Java关键字final和static的理解

    本文主要给大家谈谈小编对java关键字final和static的理解,本文给大家介绍的较详细,需要的朋友参考参考下
    2017-04-04
  • 基于Eclipce配置Spring Boot过程图解

    基于Eclipce配置Spring Boot过程图解

    这篇文章主要介绍了基于Eclipce配置Spring Boot过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • idea远程debug调试部署在tomcat上项目

    idea远程debug调试部署在tomcat上项目

    本文主要介绍了idea远程debug调试部署在tomcat上项目,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • Java在Word中添加多行图片水印

    Java在Word中添加多行图片水印

    这篇文章主要介绍了Java在Word中添加多行图片,图文讲解的很清晰,有对于这方面不懂得同学可以跟着研究下
    2021-02-02
  • 浅谈IDEA实用的Servlet模板

    浅谈IDEA实用的Servlet模板

    今天给大家分享一下IDEA实用的Servlet模板,文中有非常详细的图文介绍及代码示例,对小伙伴们很有帮助哦,需要的朋友可以参考下
    2021-05-05
  • 常用输入字节流InputStream介绍

    常用输入字节流InputStream介绍

    下面小编就为大家带来一篇常用输入字节流InputStream介绍。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • 在Mybatis中association标签多层嵌套的问题

    在Mybatis中association标签多层嵌套的问题

    这篇文章主要介绍了在Mybatis中association标签多层嵌套的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • SpringBoot集成Milvus和deeplearning4j实现图搜图功能

    SpringBoot集成Milvus和deeplearning4j实现图搜图功能

    Milvus 是一种高性能、高扩展性的向量数据库,可在从笔记本电脑到大型分布式系统等各种环境中高效运行,Deeplearning4j(DL4J)是一个开源的深度学习框架,专门为Java和Scala开发,本文给大家介绍了SpringBoot集成Milvus和deeplearning4j实现图搜图功能
    2024-10-10
  • SpringBoot+mybatis-plus实现多数据源配置的详细步骤

    SpringBoot+mybatis-plus实现多数据源配置的详细步骤

    在日益复杂的业务场景中,单一数据源往往难以满足微服务架构下的多元化需求,文将详细介绍两种主流的 MyBatis-Plus 多数据源配置方式,大家可以根据需要进行选择
    2025-08-08

最新评论