在《Spring Transaction 分析事务属性(事务的基本概念、配置)》基础上
将介绍如何实现你自己的事务同步,只要是活动的事务状态发生变化就会收到TransactionSynchronizationManager的回调。
书中的demo:
使用TransactionSynchronizationManager注册了TransactionSynchronization回调,同时MyTransactionSynchronizationAdapter会根据事务的完成状态去调用MySession.beginTransaction()、MySession.commit()或MySession.rollback()方法。
模拟一个session类:
简单模拟SessionFactory:
核心事务同步适配器:
调用起的DAO:
配置文件:
测试:
总结:有两个核心的Spring类支持了这个功能,TransactionSynchronization接口,TransactionSynchronizationManager类。
TransactionSynchronizationManager负责管理当前线程在资源,资源可以主动绑定到TransactionSynchronizationManager中。
TransactionSynchronization提供了同步调用,当方法上面定义了@Transactional注解,那么当每次状态发生时就会调用本同步适配器。
PlatformTransactionManager的各种实现也是借助了上面这两个类,你可以查阅一下源码。所以,我们自然而然的也可以自己实现一个PlatformTransactionManager,来管理真正的sessionFactory,然后像其他实现一样,交给Spring,然后再给他声明事务。
将介绍如何实现你自己的事务同步,只要是活动的事务状态发生变化就会收到TransactionSynchronizationManager的回调。
书中的demo:
使用TransactionSynchronizationManager注册了TransactionSynchronization回调,同时MyTransactionSynchronizationAdapter会根据事务的完成状态去调用MySession.beginTransaction()、MySession.commit()或MySession.rollback()方法。
模拟一个session类:
- packagecn.partner4java.myptm;
- importjava.io.Serializable;
- /**
- * 模拟一个session类
- * @author partner4java
- *
- */
- publicclassMySession {
- /** 用来标识一个session */
- privateLong sessionId;
- publicvoidsave(Serializable entity){
- System.out.println(sessionId +":save");
- }
- publicvoidbeginTransaction(){
- System.out.println(sessionId +":beginTransaction");
- }
- publicvoidcommit(){
- System.out.println(sessionId +":commit");
- }
- publicvoidrollback(){
- System.out.println(sessionId +":rollback");
- }
- publicLong getSessionId() {
- returnsessionId;
- }
- publicvoidsetSessionId(Long sessionId) {
- this.sessionId = sessionId;
- }
- @Override
- publicString toString() {
- return"MySession [sessionId="+ sessionId +"]";
- }
- }
简单模拟SessionFactory:
- packagecn.partner4java.myptm;
- importorg.springframework.transaction.support.TransactionSynchronization;
- importorg.springframework.transaction.support.TransactionSynchronizationManager;
- /**
- * 简单模拟SessionFactory<br/>
- * 通判传递的类都为MySessionFactory而不是MySession,通过MySessionFactory获得当前线程的MySession或者开启一个新的MySession
- * @author partner4java
- *
- */
- publicclassMySessionFactory {
- /**
- * 如果当前线程存在MySession,就使用该MySession,否者开启一个新的MySession
- * @return
- */
- publicMySession getSession(){
- //传入this,是因为,我们以当前factory类作为键保存的MySession
- if(TransactionSynchronizationManager.hasResource(this)){
- returngetCurrentSession();
- }else{
- returnopenSession();
- }
- }
- /**
- * 开启一个新MySession
- * @return
- */
- privateMySession openSession() {
- MySession mySession =newMySession();
- mySession.setSessionId(System.currentTimeMillis());
- //注册进当前线程管理一个Synchronization
- TransactionSynchronization transactionSynchronization =newMyTransactionSynchronizationAdapter(this);
- TransactionSynchronizationManager.registerSynchronization(transactionSynchronization);
- //绑定新开启的一个MySession进当前线程事务管理器
- TransactionSynchronizationManager.bindResource(this, mySession);
- returnmySession;
- }
- /**
- * 获取当前线程的MySession
- * @return
- */
- privateMySession getCurrentSession() {
- MySession mySession = (MySession) TransactionSynchronizationManager.getResource(this);
- returnmySession;
- }
- }
核心事务同步适配器:
- packagecn.partner4java.myptm;
- importorg.springframework.transaction.support.TransactionSynchronizationAdapter;
- importorg.springframework.transaction.support.TransactionSynchronizationManager;
- /**
- * 核心事务同步适配器<br/>
- * 当方法上面定义了@Transactional注解,那么当每次状态发生时就会调用本同步适配器
- * for transaction synchronization callbacks
- * @author partner4java
- *
- */
- publicclassMyTransactionSynchronizationAdapterextends
- TransactionSynchronizationAdapter {
- privateMySessionFactory mySessionFactory;
- publicMyTransactionSynchronizationAdapter(MySessionFactory mySessionFactory) {
- this.mySessionFactory = mySessionFactory;
- }
- @Override
- publicvoidbeforeCommit(booleanreadOnly) {
- //readOnly标识是否是一个只读线程
- if(!readOnly){
- MySession mySession = (MySession) TransactionSynchronizationManager.getResource(mySessionFactory);
- mySession.beginTransaction();
- }
- }
- @Override
- publicvoidafterCompletion(intstatus) {
- MySession mySession = (MySession) TransactionSynchronizationManager.getResource(mySessionFactory);
- if(STATUS_COMMITTED == status) {
- mySession.commit();
- }
- //当然,你还可以定义回滚方法
- }
- }
调用起的DAO:
- packagecn.partner4java.dao;
- publicinterfaceHelloDao {
- publicvoidsaveHello();
- }
- packagecn.partner4java.dao;
- importorg.springframework.jdbc.core.support.JdbcDaoSupport;
- importorg.springframework.transaction.annotation.Transactional;
- importcn.partner4java.myptm.MySessionFactory;
- /**
- * 一个hello world dao,起到模拟调用自定义事务同步的作用
- * @author partner4java
- *
- */
- publicclassHelloDaoImplextendsJdbcDaoSupportimplementsHelloDao {
- privateMySessionFactory mySessionFactory;
- publicvoidsetMySessionFactory(MySessionFactory mySessionFactory) {
- this.mySessionFactory = mySessionFactory;
- }
- @Transactional
- publicvoidsaveHello(){
- 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 =newClassPathXmlApplicationContext("/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,然后再给他声明事务。