Spring @Transactional 如何开启事务

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的上下文中查找的..


上文回顾:

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

 

 

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

 

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

 

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

 

 

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

 

[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.               TransactionInfotxInfo = 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 classAbstractPlatformTransactionManager implementsPlatformTransactionManager, 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.                                 //以键值对形式绑定到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开启事务后是以键值对形式 存放到 TransactionSynchronizationManager的上下文(ThreadLocal的Map)中(以ThreadLocal的方式与当前线程绑定).


http://blog.csdn.net/irelandken/article/details/7194046


你可能感兴趣的:(Spring)