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")

 

 

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


Public UserService
{
   @Transactional
   public void addUser(User user) throwsException
   {
      Session session =sessionFactory.getCurrentSession();
    
      session.save(user);
   }
}

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

先进入到JdkDynamicAopProxyimplements.invoke()方法

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

典型的拦截器模式:

1:按需开启事务

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

3:提交事务

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor,Serializable {
 
    public Object invoke(final MethodInvocationinvocation) throws Throwable {
                                                                                                                                                  .......
              //就在这一句开启事务
              TransactionInfotxInfo = createTransactionIfNecessary(tm, txAttr,joinpointIdentification);
              ......
              retVal= invocation.proceed();   //执行下一个拦截器 或 执行代理目标的方法
              ......                                                                                                                              //提交事务                       
              commitTransactionAfterReturning(txInfo);                                                                     
              return retVal;
              .......
    } 
}

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

 

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

AbstractPlatformTransactionManager.getTransaction()方法:

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

public abstract classAbstractPlatformTransactionManager implementsPlatformTransactionManager, Serializable {
 ......
   public final TransactionStatus getTransaction(TransactionDefinitiondefinition) throws TransactionException {
              //这里是取得当前已绑定到TransactionSynchronizationManager的上下文的事务,主要为事务传播行为而设
              Object transaction =doGetTransaction();
              ........
              //如果事务已存在,根据事务传播行为来处理,
              if(isExistingTransaction(transaction)) {
                     // Existingtransaction found -> check propagation behavior to find out how to behave.
                     return handleExistingTransaction(definition, transaction, debugEnabled);
              }
              ......
              //这里最关键,开启一个新的事务,并放进TransactionSynchronizationManager的上下文中,并绑定到当前线程)
              doBegin(transaction,definition);
              return status;
              .......
       }
......
}

HibernateTransactionManager.doGetTransaction()方法:

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

public class HibernateTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean {

	protected Object doGetTransaction() {
		HibernateTransactionObject txObject = new HibernateTransactionObject();
		......

		//在TransactionSynchronizationManager的上下文中查找当前的Session(实质上也是与线程绑定的)
		SessionHolder sessionHolder =
				(SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());

		......
		return txObject;
	}

}

HibernateTransactionManager.doBegin()方法:

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

public class HibernateTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean {
......
     protected void doBegin(Object transaction, TransactionDefinition definition) {
		
                HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;

		.........

		try {
			if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
				//这里才真正的打开Session
				Session newSession = SessionFactoryUtils.openSession(getSessionFactory());
				.........
			}

			session = txObject.getSessionHolder().getSession();

                        .........

			Transaction hibTx;

			// Register transaction timeout.
			.........
			if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
				.........
			}
			else {
				//这里才真正地开启事务
				hibTx = session.beginTransaction();
			}

			.........

                        //如果这新开启的Session,则将SessionHolder(Session和Transaction)放到TransactionSynchronizationManager的上下文中(绑定到当前线程)
			// Bind the session holder to the thread.

			if (txObject.isNewSessionHolder()) {                                                                                                        
                                //以键值对<SessionFactory,SessionHolder>形式绑定到TransactionSynchronizationManager的上下文中
				TransactionSynchronizationManager.bindResource(getSessionFactory(), txObject.getSessionHolder());
			}
			
			.......
		}

		.........
     }
......
}

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的方式与当前线程绑定).

<div class="dp-highlighter bg_java"><div class="bar"><div class="tools"><b>[java]</b> <a href="#" class="ViewSource" title="view plain" οnclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><a href="#" class="CopyToClipboard" title="copy" οnclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><a href="#" class="PrintSource" title="print" οnclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a><a href="#" class="About" title="?" οnclick="dp.sh.Toolbar.Command('About',this);return false;">?</a><div style="position: absolute; left: 0px; top: 0px; width: 0px; height: 0px; z-index: 99;"><embed id="ZeroClipboardMovie_8" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" loop="false" menu="false" quality="best" bgcolor="#ffffff" name="ZeroClipboardMovie_8" allowscriptaccess="always" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="id=8&width=0&height=0" wmode="transparent" align="middle" height="0" width="0"></div></div></div><ol class="dp-j" start="1"><li class="alt"><span><span><pre></pre>  </span></span></li><li class=""><span><pre></pre>  </span></li><li class="alt"><span><pre></pre>  </span></li><li class=""><span><pre></pre>  </span></li><li class="alt"><span><pre></pre>  </span></li><li class=""><span><pre></pre>  </span></li><li class="alt"><span><pre></pre>  </span></li><li class=""><span><pre></pre>  </span></li><li class="alt"><span><pre></pre>  </span></li><li class=""><span><pre></pre>  </span></li><li class="alt"><span><pre></pre>  </span></li><li class=""><span><pre></pre>  </span></li><li class="alt"><span><pre></pre>  </span></li><li class=""><span><pre></pre>  </span></li><li class="alt"><span><pre></pre>  </span></li><li class=""><span><pre></pre>  </span></li><li class="alt"><span><pre></pre>  </span></li><li class=""><span><pre></pre>  </span></li><li class="alt"><span><pre></pre>  </span></li><li class=""><span><pre></pre>  </span></li><li class="alt"><span><pre></pre>  </span></li><li class=""><span><pre></pre>  </span></li><li class="alt"><span><pre></pre>  </span></li><li class=""><span><pre></pre>  </span></li><li class="alt"><span><pre></pre>  </span></li></ol></div><pre style="display: none;" name="code" class="java"><pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>
<pre></pre>

</pre>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智能体格

你的鼓将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值