原文 :http://blog.csdn.net/partner4java/article/details/7017398
将介绍如何实现你自己的事务同步,只要是活动的事务状态发生变化就会收到TransactionSynchronizationManager的回调。
书中的demo:
使用TransactionSynchronizationManager注册了TransactionSynchronization回调,同时 MyTransactionSynchronizationAdapter会根据事务的完成状态去调用 MySession.beginTransaction()、MySession.commit()或MySession.rollback()方法。
模拟一个session类:
- package cn.partner4java.myptm;
- import java.io.Serializable;
- /**
- * 模拟一个session类
- * @author partner4java
- *
- */
- public class MySession {
- /** 用来标识一个session */
- private Long sessionId;
- public void save(Serializable entity){
- System.out.println(sessionId + ":save");
- }
- public void beginTransaction(){
- System.out.println(sessionId + ":beginTransaction");
- }
- public void commit(){
- System.out.println(sessionId + ":commit");
- }
- public void rollback(){
- System.out.println(sessionId + ":rollback");
- }
- public Long getSessionId() {
- return sessionId;
- }
- public void setSessionId(Long sessionId) {
- this.sessionId = sessionId;
- }
- @Override
- public String toString() {
- return "MySession [sessionId=" + sessionId + "]";
- }
- }
简单模拟SessionFactory:
- package cn.partner4java.myptm;
- import org.springframework.transaction.support.TransactionSynchronization;
- import org.springframework.transaction.support.TransactionSynchronizationManager;
- /**
- * 简单模拟SessionFactory<br/>
- * 通判传递的类都为MySessionFactory而不是MySession,通过MySessionFactory获得当前线程的MySession或者开启一个新的MySession
- * @author partner4java
- *
- */
- public class MySessionFactory {
- /**
- * 如果当前线程存在MySession,就使用该MySession,否者开启一个新的MySession
- * @return
- */
- public MySession getSession(){
- //传入this,是因为,我们以当前factory类作为键保存的MySession
- if(TransactionSynchronizationManager.hasResource(this)){
- return getCurrentSession();
- }else{
- return openSession();
- }
- }
- /**
- * 开启一个新MySession
- * @return
- */
- private MySession openSession() {
- MySession mySession = new MySession();
- mySession.setSessionId(System.currentTimeMillis());
- //注册进当前线程管理一个Synchronization
- TransactionSynchronization transactionSynchronization = new MyTransactionSynchronizationAdapter(this);
- TransactionSynchronizationManager.registerSynchronization(transactionSynchronization);
- //绑定新开启的一个MySession进当前线程事务管理器
- TransactionSynchronizationManager.bindResource(this, mySession);
- return mySession;
- }
- /**
- * 获取当前线程的MySession
- * @return
- */
- private MySession getCurrentSession() {
- MySession mySession = (MySession) TransactionSynchronizationManager.getResource(this);
- return mySession;
- }
- }
核心事务同步适配器:
- package cn.partner4java.myptm;
- import org.springframework.transaction.support.TransactionSynchronizationAdapter;
- import org.springframework.transaction.support.TransactionSynchronizationManager;
- /**
- * 核心事务同步适配器<br/>
- * 当方法上面定义了@Transactional注解,那么当每次状态发生时就会调用本同步适配器
- * for transaction synchronization callbacks
- * @author partner4java
- *
- */
- public class MyTransactionSynchronizationAdapter extends
- TransactionSynchronizationAdapter {
- private MySessionFactory mySessionFactory;
- public MyTransactionSynchronizationAdapter(MySessionFactory mySessionFactory) {
- this.mySessionFactory = mySessionFactory;
- }
- @Override
- public void beforeCommit(boolean readOnly) {
- //readOnly标识是否是一个只读线程
- if(!readOnly){
- MySession mySession = (MySession) TransactionSynchronizationManager.getResource(mySessionFactory);
- mySession.beginTransaction();
- }
- }
- @Override
- public void afterCompletion(int status) {
- MySession mySession = (MySession) TransactionSynchronizationManager.getResource(mySessionFactory);
- if (STATUS_COMMITTED == status) {
- mySession.commit();
- }
- //当然,你还可以定义回滚方法
- }
- }
调用起的DAO:
- package cn.partner4java.dao;
- public interface HelloDao {
- public void saveHello();
- }
- package cn.partner4java.dao;
- import org.springframework.jdbc.core.support.JdbcDaoSupport;
- import org.springframework.transaction.annotation.Transactional;
- import cn.partner4java.myptm.MySessionFactory;
- /**
- * 一个hello world dao,起到模拟调用自定义事务同步的作用
- * @author partner4java
- *
- */
- public class HelloDaoImpl extends JdbcDaoSupport implements HelloDao {
- private MySessionFactory mySessionFactory;
- public void setMySessionFactory(MySessionFactory mySessionFactory) {
- this.mySessionFactory = mySessionFactory;
- }
- @Transactional
- public void saveHello(){
- mySessionFactory.getSession().save(null);
- this.getJdbcTemplate().execute("select * from user");
- }
- }
配置文件:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop.xsd">
- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close">
- <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
- <property name="url" value="jdbc:mysql://localhost:3306/springdb"/>
- <property name="username" value="root"/>
- <property name="password" value="123456"/>
- </bean>
- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource"/>
- </bean>
- <tx:annotation-driven transaction-manager="transactionManager"/>
- <aop:aspectj-autoproxy />
- <bean id="mySessionFactory" class="cn.partner4java.myptm.MySessionFactory"/>
- <bean id="helloDao" class="cn.partner4java.dao.HelloDaoImpl">
- <property name="dataSource" ref="dataSource"/>
- <property name="mySessionFactory" ref="mySessionFactory"></property>
- </bean>
- </beans>
测试:
- ApplicationContext ac = new ClassPathXmlApplicationContext("/META-INF/spring/myptm.xml");
- HelloDao helloDao = (HelloDao) ac.getBean("helloDao");
- helloDao.saveHello();
- // 后台打印:
- // 1322395163008:save
- // 1322395163008:beginTransaction
- // 1322395163008:commit
总结:有两个核心的Spring类支持了这个功能,TransactionSynchronization接口,TransactionSynchronizationManager类。
TransactionSynchronizationManager负责管理当前线程在资源,资源可以主动绑定到TransactionSynchronizationManager中。
TransactionSynchronization提供了同步调用,当方法上面定义了@Transactional注解,那么当每次状态发生时就会调用本同步适配器。
PlatformTransactionManager的各种实现也是借助了上面这两个类,你可以查阅一下源码。所以,我们自然而然的也可以自己实现一个 PlatformTransactionManager,来管理真正的sessionFactory,然后像其他实现一样,交给Spring,然后再给他 声明事务。