Spring @Transactional 如何开启事务
来源:互联网 发布:薛之谦淘宝店铺链接 编辑:程序博客网 时间:2024/05/17 23:21
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 AbstractPlatformTransactionManagerimplements 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 AbstractPlatformTransactionManagerimplements ResourceTransactionManager, InitializingBean {...... protected void doBegin(Object transaction, TransactionDefinition definition) { HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;.........try {if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {//这里才真正的打开SessionSession 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" onclick="dp.sh.Toolbar.Command('ViewSource',this);return false;">view plain</a><a href="#" class="CopyToClipboard" title="copy" onclick="dp.sh.Toolbar.Command('CopyToClipboard',this);return false;">copy</a><a href="#" class="PrintSource" title="print" onclick="dp.sh.Toolbar.Command('PrintSource',this);return false;">print</a><a href="#" class="About" title="?" onclick="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>
- Spring @Transactional 如何开启事务
- Spring @Transactional 如何开启事务
- Spring @Transactional 如何开启事务
- Spring 的@Transactional 如何开启事务
- Spring中@Transactional什么时候开启事务?
- @Transactional spring 配置事务
- spring 事务注解@Transactional
- spring 事务注解@Transactional
- spring 事务注解@Transactional
- spring @transactional事务
- spring 事务 Transactional
- Spring @Transactional事务浅谈
- Spring注解事务@Transactional
- Spring 的 @Transactional事务
- Spring 注解@Transactional 事务
- Spring @Transactional 事务机制
- Spring 之注解事务 @Transactional
- Spring 之注解事务 @Transactional
- ArrayList的三种排序法
- 常见时间复杂度排行
- 判断字符串是否为 utf-8 编码
- IBatis.Net与IBatisNet中ExecuteQueryForMap和QueryForDictionary的用法
- spring3.0事务的多数据源的annotation-driven用法
- Spring @Transactional 如何开启事务
- TextView/EditText 使用注意地方
- 图像拼接中的RANSAC算法
- Android配置QQ邮箱问题
- 【LeetCode】Swap Nodes in Pairs
- Linux设置环境变量小结:设置永久变量&临时变量 全局变量&局部变量
- Armstrong数问题
- U盘明明有空间 但复制大文件显示磁盘已满
- 酷派7296刷机包 高仿IOS美化 细节精仿