spring(自定义事物同步TransactionSynchronizationManager)

spring(自定义事物同步TransactionSynchronizationManager)



将介绍如何实现你自己的事务同步,只要是活动的事务状态发生变化就会收到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,然后再给他声明事务。