Spring 的@Transactional 如何开启事务

java.lang.Object

  org.springframework.transaction.support.TransactionSynchronizationManager


public abstract class TransactionSynchronizationManager

extends Object

Central helper that manages resourcesand transaction synchronizations per thread.

为每个线程管理资源和事务的中心helper


 hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext时,

@Transactional,Spring的事务管理器HibernateTransactionManager.doBegin()方法开启的Session和事务 就是绑定到TransactionSynchronizationManager的上下文(ThreadLocal的Map)中的。

 SpringSessionContext.currentSesssion()方法就是在TransactionSynchronizationManager的上下文中查找session。


配置:

<!-- 事务管理器 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    <!--  注解驱动:解析@Transactional注解,对@Transactional注解的方法用指定的事务管理器实现事务管理  -->
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>



上文回顾:

现在对于hibernate.current_session_context_class= org.springframework.orm.hibernate4.SpringSessionContext时的getCurrentSession()就很清楚了:

 

1:@Transactional声明的方法执行时,Spring的TransactionManager会自动Open Sesion,自动开启事务,并且将此Sesion绑定到SpringSessionContext(实际上是TransactionSynchronizationManager的上下文中)中。

 

2:SessionFactory.getCurrentSession()方法执行时,调用SpringSessionContext.currentSession()从TransactionSynchronizationManager的上下文中查找 当前的Session。


3:找到后返回当前的Session,找不到,则返回HibernateException("No Session found for current thread")



spring 的事务管理架构:


1.接口:PlatformTransactionManager。

该接口只有三个方法:

(1)TransactionStatus getTransaction(TransactionDefinition definition)

  该方法的作用是:依据指定的事务定义返回当前存在的事务或者是创建一个新的事务。这是入口。

(2)void commit(TransactionStatus status)

(3)void rollback(TransactionStatus status)

2.抽象类:public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable


该抽象类实现了接口PlatformTransactionManager定义的getTransaction(TransactionDefinition definition) 方法,并且是final类型的方法,

这就意味着具体的实现类都是用这个方法获取事务的。方法内部调用doGetTransaction()方法用以获取当前存在的事务,若是当前存在事务则取出并且依据指定的事务传播行为处理。这个方法是抽象的,交给具体的事务管理器实现。若是当前不存在事务,则调用doBegin()方法创建一个事务并且绑定到TransactionSynchronizationManager的上下文(ThreadLocal的Map)中,绑定到当前线程。doBegin()方法也是抽象的,交给具体的事务管理器实现。


3.具体的事务管理器:

public class HibernateTransactionManager extends AbstractPlatformTransactionManager
implements ResourceTransactionManager, BeanFactoryAware, InitializingBean 

HibernateTransactionManager 实现了抽象类中的doGetTransaction()和doBegin()方法。



 

 

上述第一点是未验证的,现在我们来分析一下源代码:

 

[java]  view plain copy
  1. Public UserService  
  2. {  
  3.    @Transactional  
  4.    public void addUser(User user) throwsException  
  5.    {  
  6.       Session session =sessionFactory.getCurrentSession();  
  7.       
  8.       session.save(user);  
  9.    }  
  10. }  



[java]  view plain copy
  1. //当然,声明式事务管理实质也是用AOP实现的,此时取得的一个Proxy..  
  2. UserService userService = (UserService) beanFactory.getBean("userService");  
  3.                
  4. User user = new User();  
  5. user.setName("Mark");  
  6.                
  7. userService.addUser(user);  //在执行这一句时,应该是调用Proxy来开启一个事务,并绑定到某个上下文中,我们跟进去看看  


先进入到JdkDynamicAopProxyimplements.invoke()方法

然后到ReflectiveMethodInvocation. proceed(),这里调用TransactionInterceptor.invoke(this)方法: 

典型的拦截器模式:

1:按需开启事务

2:递归执行下一个拦截器 或 执行代理目标方法

3:提交事务

[java]  view plain copy
  1. public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor,Serializable {  
  2.    
  3.     public Object invoke(final MethodInvocationinvocation) throws Throwable {  
  4.                                                                                                                                                   .......  
  5.               //就在这一句开启事务  
  6.               TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr,joinpointIdentification);  
  7.               ......  
  8.               retVal= invocation.proceed();   //执行下一个拦截器 或 执行代理目标的方法  
  9.               ......                                                                                                                              //提交事务                         
  10.               commitTransactionAfterReturning(txInfo);                                                                       
  11.               return retVal;  
  12.               .......  
  13.     }   
  14. }  


进入createTransactionIfNecessary(tm,txAttr, joinpointIdentification), 其中的tm.getTransaction(txAttr);    //这一句应该是取得事务的,跟进去

……………………………………….

AbstractPlatformTransactionManager.getTransaction()方法:

如果当前有事务,取出并根据事务传播行为的配置去处理,如果当前没有事务,调用doBegin开启一个新事务


[java]  view plain copy
  1. public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {  
  2.  ......  
  3.    public final TransactionStatus getTransaction(TransactionDefinitiondefinition) throws TransactionException {  
  4.               //这里是取得当前已绑定到TransactionSynchronizationManager的上下文的事务,主要为事务传播行为而设  
  5.               Object transaction =doGetTransaction();  
  6.               ........  
  7.               //如果事务已存在,根据事务传播行为来处理,  
  8.               if(isExistingTransaction(transaction)) {  
  9.                      // Existingtransaction found -> check propagation behavior to find out how to behave.  
  10.                      return handleExistingTransaction(definition, transaction, debugEnabled);  
  11.               }  
  12.               ......  
  13.               //这里最关键,开启一个新的事务,并放进TransactionSynchronizationManager的上下文中,并绑定到当前线程)  
  14.               doBegin(transaction,definition);  
  15.               return status;  
  16.               .......  
  17.        }  
  18. ......  
  19. }  

 

HibernateTransactionManager.doGetTransaction()方法:

尝试获取当前已绑定到TransactionSynchronizationManager的上下文的事务,主要为事务传播行为而设


[java]  view plain copy
  1. public class HibernateTransactionManager extends AbstractPlatformTransactionManager  
  2.         implements ResourceTransactionManager, InitializingBean {  
  3.   
  4.     protected Object doGetTransaction() {  
  5.         HibernateTransactionObject txObject = new HibernateTransactionObject();  
  6.         ......  
  7.   
  8.         //在TransactionSynchronizationManager的上下文中查找当前的Session(实质上也是与线程绑定的)  
  9.         SessionHolder sessionHolder =  
  10.                 (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());  
  11.   
  12.         ......  
  13.         return txObject;  
  14.     }  
  15.   
  16. }  


HibernateTransactionManager.doBegin()方法:

开启一个新的事务,并放进TransactionSynchronizationManager的上下文(ThreadLocal的Map)中,绑定到当前线程)

[java]  view plain copy
  1. public class HibernateTransactionManager extends AbstractPlatformTransactionManager  
  2.         implements ResourceTransactionManager, InitializingBean {  
  3. ......  
  4.      protected void doBegin(Object transaction, TransactionDefinition definition) {  
  5.           
  6.                 HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;  
  7.   
  8.         .........  
  9.   
  10.         try {  
  11.             if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {  
  12.                 //这里才真正的打开Session  
  13.                 Session newSession = SessionFactoryUtils.openSession(getSessionFactory());  
  14.                 .........  
  15.             }  
  16.   
  17.             session = txObject.getSessionHolder().getSession();  
  18.   
  19.                         .........  
  20.   
  21.             Transaction hibTx;  
  22.   
  23.             // Register transaction timeout.  
  24.             .........  
  25.             if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {  
  26.                 .........  
  27.             }  
  28.             else {  
  29.                 //这里才真正地开启事务  
  30.                 hibTx = session.beginTransaction();  
  31.             }  
  32.   
  33.             .........  
  34.   
  35.                         //如果这新开启的Session,则将SessionHolder(Session和Transaction)放到TransactionSynchronizationManager的上下文中(绑定到当前线程)  
  36.             // Bind the session holder to the thread.  
  37.   
  38.             if (txObject.isNewSessionHolder()) {                                                                                                          
  39.                                 //以键值对<SessionFactory,SessionHolder>形式绑定到TransactionSynchronizationManager的上下文中  
  40.                 TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder());  
  41.             }  
  42.               
  43.             .......  
  44.         }  
  45.   
  46.         .........  
  47.      }  
  48. ......  
  49. }  



Spring @Transactional 如何开启事务 总结:


@Transactional声明的方法执行时会调用AbstractPlatformTransactionManager.getTransaction()取得当前事务。


而getTransaction()的执行流程如下:

1:尝试获取当前已绑定到TransactionSynchronizationManager的上下文的事务

(调用HibernateTransactionManager.doGetTransaction()方法)


2:如果取得已存在的事务,则根据事务传播属性的设置来处理

(调用AbstractPlatformTransactionManager.handleExistingTransaction()方法)


3:如果没有事务,则打开新的Session,开启新的事务,并将该Session和事务绑定到TransactionSynchronizationManager的上下文中(调用HibernateTransactionManager.doBegin()方法)



-------------------------------------------------

核心还是理解TransactionSynchronizationManager,要懂得Spring的TransactionManager开启事务后是以键值对<SessionFactory,SessionHolder>形式 存放到 TransactionSynchronizationManager的上下文(ThreadLocal的Map)中(以ThreadLocal的方式与当前线程绑定).

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值