Spring 实现你自己的事务同步

本文介绍了如何利用Spring的TransactionSynchronizationManager和TransactionSynchronization接口来自定义事务同步逻辑,包括模拟SessionFactory、Session及事务同步适配器的具体实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在《Spring Transaction 分析事务属性(事务的基本概念、配置)》基础上 



将介绍如何实现你自己的事务同步,只要是活动的事务状态发生变化就会收到TransactionSynchronizationManager的回调。 

书中的demo: 
使用TransactionSynchronizationManager注册了TransactionSynchronization回调,同时MyTransactionSynchronizationAdapter会根据事务的完成状态去调用MySession.beginTransaction()、MySession.commit()或MySession.rollback()方法。
 

模拟一个session类:
  1. package cn.partner4java.myptm;  
  2.   
  3. import java.io.Serializable;  
  4.   
  5. /** 
  6. * 模拟一个session类 
  7. * @author partner4java 
  8. * 
  9. */  
  10. public class MySession {  
  11.     /** 用来标识一个session */  
  12.     private Long sessionId;  
  13.   
  14.     public void save(Serializable entity){  
  15.         System.out.println(sessionId + ":save");  
  16.     }  
  17.       
  18.     public void beginTransaction(){  
  19.         System.out.println(sessionId + ":beginTransaction");  
  20.     }  
  21.       
  22.     public void commit(){  
  23.         System.out.println(sessionId + ":commit");  
  24.     }  
  25.       
  26.     public void rollback(){  
  27.         System.out.println(sessionId + ":rollback");  
  28.     }  
  29.       
  30.     public Long getSessionId() {  
  31.         return sessionId;  
  32.     }  
  33.   
  34.     public void setSessionId(Long sessionId) {  
  35.         this.sessionId = sessionId;  
  36.     }  
  37.   
  38.     @Override  
  39.     public String toString() {  
  40.         return "MySession [sessionId=" + sessionId + "]";  
  41.     }  
  42.   
  43.       
  44. }  

简单模拟SessionFactory:
  1. package cn.partner4java.myptm;  
  2.   
  3. import org.springframework.transaction.support.TransactionSynchronization;  
  4. import org.springframework.transaction.support.TransactionSynchronizationManager;  
  5.   
  6.   
  7. /** 
  8. * 简单模拟SessionFactory<br/> 
  9. * 通判传递的类都为MySessionFactory而不是MySession,通过MySessionFactory获得当前线程的MySession或者开启一个新的MySession 
  10. * @author partner4java 
  11. * 
  12. */  
  13. public class MySessionFactory {  
  14.       
  15.     /** 
  16.      * 如果当前线程存在MySession,就使用该MySession,否者开启一个新的MySession 
  17.      * @return 
  18.      */  
  19.     public MySession getSession(){  
  20.         //传入this,是因为,我们以当前factory类作为键保存的MySession  
  21.         if(TransactionSynchronizationManager.hasResource(this)){  
  22.             return getCurrentSession();  
  23.         }else{  
  24.             return openSession();  
  25.         }  
  26.           
  27.     }  
  28.   
  29.       
  30.     /** 
  31.      * 开启一个新MySession 
  32.      * @return 
  33.      */  
  34.     private MySession openSession() {  
  35.         MySession mySession = new MySession();  
  36.         mySession.setSessionId(System.currentTimeMillis());  
  37.           
  38.         //注册进当前线程管理一个Synchronization  
  39.         TransactionSynchronization transactionSynchronization = new MyTransactionSynchronizationAdapter(this);  
  40.         TransactionSynchronizationManager.registerSynchronization(transactionSynchronization);  
  41.           
  42.         //绑定新开启的一个MySession进当前线程事务管理器  
  43.         TransactionSynchronizationManager.bindResource(this, mySession);  
  44.           
  45.         return mySession;  
  46.     }  
  47.   
  48.     /** 
  49.      * 获取当前线程的MySession 
  50.      * @return 
  51.      */  
  52.     private MySession getCurrentSession() {  
  53.         MySession mySession = (MySession) TransactionSynchronizationManager.getResource(this);  
  54.         return mySession;  
  55.     }  
  56. }  

核心事务同步适配器:
  1. package cn.partner4java.myptm;  
  2.   
  3. import org.springframework.transaction.support.TransactionSynchronizationAdapter;  
  4. import org.springframework.transaction.support.TransactionSynchronizationManager;  
  5.   
  6. /** 
  7. * 核心事务同步适配器<br/> 
  8. * 当方法上面定义了@Transactional注解,那么当每次状态发生时就会调用本同步适配器 
  9. * for transaction synchronization callbacks 
  10. * @author partner4java 
  11. * 
  12. */  
  13. public class MyTransactionSynchronizationAdapter extends  
  14.         TransactionSynchronizationAdapter {  
  15.     private MySessionFactory mySessionFactory;  
  16.   
  17.     public MyTransactionSynchronizationAdapter(MySessionFactory mySessionFactory) {  
  18.         this.mySessionFactory = mySessionFactory;  
  19.     }  
  20.   
  21.   
  22.     @Override  
  23.     public void beforeCommit(boolean readOnly) {  
  24.         //readOnly标识是否是一个只读线程  
  25.         if(!readOnly){  
  26.             MySession mySession = (MySession) TransactionSynchronizationManager.getResource(mySessionFactory);  
  27.             mySession.beginTransaction();  
  28.         }  
  29.     }  
  30.   
  31.     @Override  
  32.     public void afterCompletion(int status) {  
  33.         MySession mySession = (MySession) TransactionSynchronizationManager.getResource(mySessionFactory);  
  34.         if (STATUS_COMMITTED == status) {  
  35.             mySession.commit();  
  36.         }  
  37.         //当然,你还可以定义回滚方法  
  38.     }  
  39.       
  40.       
  41. }  

调用起的DAO:
  1. package cn.partner4java.dao;  
  2.   
  3. public interface HelloDao {  
  4.     public void saveHello();  
  5. }  

  1. package cn.partner4java.dao;  
  2.   
  3. import org.springframework.jdbc.core.support.JdbcDaoSupport;  
  4. import org.springframework.transaction.annotation.Transactional;  
  5.   
  6. import cn.partner4java.myptm.MySessionFactory;  
  7.   
  8. /** 
  9. * 一个hello world dao,起到模拟调用自定义事务同步的作用 
  10. * @author partner4java 
  11. * 
  12. */  
  13. public class HelloDaoImpl extends JdbcDaoSupport implements HelloDao {  
  14.     private MySessionFactory mySessionFactory;  
  15.   
  16.     public void setMySessionFactory(MySessionFactory mySessionFactory) {  
  17.         this.mySessionFactory = mySessionFactory;  
  18.     }  
  19.       
  20.     @Transactional  
  21.     public void saveHello(){  
  22.         mySessionFactory.getSession().save(null);  
  23.         this.getJdbcTemplate().execute("select * from user");  
  24.     }  
  25. }  


配置文件:
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:aop="http://www.springframework.org/schema/aop"  
  4.        xmlns:tx="http://www.springframework.org/schema/tx"  
  5.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  6.        xsi:schemaLocation="  
  7.             http://www.springframework.org/schema/beans  
  8.             http://www.springframework.org/schema/beans/spring-beans.xsd  
  9.             http://www.springframework.org/schema/tx  
  10.             http://www.springframework.org/schema/tx/spring-tx.xsd  
  11.             http://www.springframework.org/schema/aop  
  12.             http://www.springframework.org/schema/aop/spring-aop.xsd">  
  13.                   
  14.     <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close">  
  15.         <property name="driverClassName" value="com.mysql.jdbc.Driver"/>  
  16.         <property name="url" value="jdbc:mysql://localhost:3306/springdb"/>  
  17.         <property name="username" value="root"/>  
  18.         <property name="password" value="123456"/>  
  19.     </bean>  
  20.   
  21.     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
  22.         <property name="dataSource" ref="dataSource"/>  
  23.     </bean>  
  24.       
  25.     <tx:annotation-driven transaction-manager="transactionManager"/>  
  26.                   
  27.     <aop:aspectj-autoproxy />  
  28.       
  29.     <bean id="mySessionFactory" class="cn.partner4java.myptm.MySessionFactory"/>  
  30.       
  31.     <bean id="helloDao" class="cn.partner4java.dao.HelloDaoImpl">  
  32.         <property name="dataSource" ref="dataSource"/>  
  33.         <property name="mySessionFactory" ref="mySessionFactory"></property>  
  34.     </bean>  
  35.   
  36. </beans>  


测试:
  1.          ApplicationContext ac = new ClassPathXmlApplicationContext("/META-INF/spring/myptm.xml");  
  2.            
  3.          HelloDao helloDao = (HelloDao) ac.getBean("helloDao");  
  4.          helloDao.saveHello();  
  5. //       后台打印:  
  6. //       1322395163008:save  
  7. //       1322395163008:beginTransaction  
  8. //       1322395163008:commit  

总结:有两个核心的Spring类支持了这个功能,TransactionSynchronization接口,TransactionSynchronizationManager类。 
TransactionSynchronizationManager负责管理当前线程在资源,资源可以主动绑定到TransactionSynchronizationManager中。 
TransactionSynchronization提供了同步调用,当方法上面定义了@Transactional注解,那么当每次状态发生时就会调用本同步适配器。 

PlatformTransactionManager的各种实现也是借助了上面这两个类,你可以查阅一下源码。所以,我们自然而然的也可以自己实现一个PlatformTransactionManager,来管理真正的sessionFactory,然后像其他实现一样,交给Spring,然后再给他声明事务。 
<think>嗯,用户问的是关于Spring Boot注册事务同步的内容。我需要先理解什么是事务同步,然后结合Spring Boot来回答。记得用户可能对Spring事务管理不太熟悉,所以需要先解释基本概念。 首先,事务同步应该是指在事务的不同阶段执行自定义逻辑。比如,在事务提交前或提交后做一些操作。Spring中的TransactionSynchronization接口应该就是这个用途的。需要说明如何注册这些同步器,以及它们的使用场景。 然后,用户可能想知道具体的实现步骤。比如,如何实现TransactionSynchronization接口,重写那些方法,比如afterCommit、afterCompletion等。还要提到在编程式事务中如何注册,使用TransactionSynchronizationManager.registerSynchronization()方法。 可能需要举个例子,比如记录日志,发送消息等。同时要提醒用户注意事务的传播机制和线程绑定问题,确保同步器在正确的事务上下文中执行。 另外,用户可能分不清声明式事务和编程式事务的区别,这里需要说明注册事务同步通常是在编程式事务中使用,或者在带有@Transactional注解的方法中结合使用。 还要注意事务同步的执行顺序和可能出现的异常处理,避免影响主事务。最后,可以提一下结合Spring Boot的自动配置,简化事务管理配置,比如使用JPA或JDBC时的自动事务管理器配置。 需要确保回答结构清晰,先介绍概念,再讲实现步骤,然后是示例代码和注意事项。语言要口语化,避免技术术语过多,必要时解释术语。检查是否有遗漏的关键点,比如事务同步的触发时机和使用限制。</think>在 Spring Boot 中,**事务同步Transaction Synchronization)** 是一种机制,允许你在事务的生命周期关键阶段(如提交、回滚等)插入自定义逻辑。通过注册事务同步器(`TransactionSynchronization`),可以实现事务完成后的回调操作,例如发送消息、清理资源或异步处理等。 --- ### **核心概念** 1. **`TransactionSynchronization` 接口** Spring 提供了此接口,定义了事务事件回调方法,例如: - `afterCommit()`: 事务成功提交后触发。 - `afterCompletion(int status)`: 事务完成后触发(无论提交或回滚)。 - `beforeCommit(boolean readOnly)`: 事务提交前触发。 2. **事务同步的作用** 在事务的边界(提交/回滚)执行与事务相关的副作用操作,例如: - 事务提交后发送消息(确保消息发送与事务一致)。 - 事务回滚后清理临时数据。 - 记录事务审计日志。 --- ### **实现步骤(Spring Boot 中)** #### 1. 实现 `TransactionSynchronization` 接口 ```java public class CustomTransactionSynchronization implements TransactionSynchronization { @Override public void afterCommit() { // 事务提交后的逻辑(例如发送消息) System.out.println("Transaction committed!"); } @Override public void afterCompletion(int status) { if (status == STATUS_COMMITTED) { System.out.println("Transaction completed with commit."); } else if (status == STATUS_ROLLED_BACK) { System.out.println("Transaction rolled back."); } } } ``` #### 2. 注册事务同步器 在事务上下文中,通过 `TransactionSynchronizationManager` 注册同步器: ```java @Service public class MyService { @Autowired private PlatformTransactionManager transactionManager; @Transactional public void doSomething() { // 业务逻辑... // 注册事务同步 TransactionSynchronizationManager.registerSynchronization( new CustomTransactionSynchronization() ); } } ``` --- ### **关键注意事项** 1. **事务绑定线程** 确保在事务活动线程中注册同步器(通常在 `@Transactional` 方法内部)。 2. **事务传播机制** 同步器仅对当前事务有效,嵌套事务需注意传播行为(如 `PROPAGATION_REQUIRES_NEW` 会创建新事务)。 3. **异步处理** 若在 `afterCommit` 中执行耗时操作,建议异步化(如使用 `@Async`)。 4. **异常处理** 同步器中的异常不会影响主事务,但需自行捕获处理。 --- ### **使用场景示例** - **提交后发消息**:保证消息只在事务提交后发送(避免脏数据)。 - **资源清理**:事务回滚后删除临时文件。 - **审计日志**:记录事务提交/回滚的详细信息。 --- ### **结合 Spring Boot 特性** Spring Boot 自动配置事务管理器(如 `DataSourceTransactionManager`),简化了事务同步的集成。你只需: 1. 添加 `@EnableTransactionManagement`(默认已启用)。 2. 使用 `@Transactional` 注解标记事务方法。 3.事务方法中注册同步器。 通过这种方式,你可以灵活扩展事务生命周期,实现事务与其他组件的协同工作。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值