spring事务从底层掌握其实现原理

  • 首页
                                </a>
                                
                              </li><li class="active ">
                                <a data-report-click="{&quot;mod&quot;:&quot;popu_336&quot;,&quot;dest&quot;:&quot;https://blog.csdn.net/&quot;,&quot;spm&quot;:&quot;3001.4477&quot;}" data-report-query="spm=3001.4477" href="https://blog.csdn.net/">
                                  博客
                                  
                                </a>
                                
                              </li><li class="">
                                <a data-report-click="{&quot;mod&quot;:&quot;popu_336&quot;,&quot;dest&quot;:&quot;https://edu.csdn.net/&quot;,&quot;spm&quot;:&quot;3001.4482&quot;}" data-report-query="spm=3001.4482" href="https://edu.csdn.net/">
                                  专栏·视频
                                  
                                </a>
                                
                              </li><li class="">
                                <a data-report-click="{&quot;mod&quot;:&quot;popu_336&quot;,&quot;dest&quot;:&quot;https://download.csdn.net/&quot;,&quot;spm&quot;:&quot;3001.4483&quot;}" data-report-query="spm=3001.4483" href="https://download.csdn.net/">
                                  下载
                                  
                                </a>
                                
                              </li><li class="">
                                <a data-report-click="{&quot;mod&quot;:&quot;popu_336&quot;,&quot;dest&quot;:&quot;https://bbs.csdn.net/&quot;,&quot;spm&quot;:&quot;3001.4491&quot;}" data-report-query="spm=3001.4491" href="https://bbs.csdn.net/">
                                  论坛
                                  
                                </a>
                                
                              </li><li class="">
                                <a data-report-click="{&quot;mod&quot;:&quot;popu_336&quot;,&quot;dest&quot;:&quot;https://ask.csdn.net/&quot;,&quot;spm&quot;:&quot;3001.4492&quot;}" data-report-query="spm=3001.4492" href="https://ask.csdn.net/">
                                  问答
                                  
                                </a>
                                
                              </li><li class="">
                                <a data-report-click="{&quot;mod&quot;:&quot;popu_336&quot;,&quot;dest&quot;:&quot;https://codechina.csdn.net/?utm_source=csdn_toolbar&quot;,&quot;spm&quot;:&quot;3001.4493&quot;}" data-report-query="spm=3001.4493" href="https://codechina.csdn.net/?utm_source=csdn_toolbar">
                                  代码
                                  
                                </a>
                                
                              </li><li class="">
                                <a data-report-click="{&quot;mod&quot;:&quot;popu_336&quot;,&quot;dest&quot;:&quot;https://codechina.csdn.net/?utm_source=csdn_toolbar&quot;,&quot;spm&quot;:&quot;3001.5342&quot;}" data-report-query="spm=3001.5342" href="https://live.csdn.net/?utm_source=csdn_toolbar">
                                  直播
                                  
                                </a>
                                
                              </li><li class="">
                                <a data-report-click="{&quot;mod&quot;:&quot;popu_336&quot;,&quot;dest&quot;:&quot;https://ac.csdn.net/&quot;,&quot;spm&quot;:&quot;3001.5716&quot;}" data-report-query="spm=3001.5716" href="https://ac.csdn.net/">
                                  能力认证
                                  
                                </a>
                                
                              </li><li class="">
                                <a data-report-click="{&quot;mod&quot;:&quot;popu_336&quot;,&quot;dest&quot;:&quot;https://studentclub.csdn.net/&quot;,&quot;spm&quot;:&quot;3001.5717&quot;}" data-report-query="spm=3001.5717" href="https://studentclub.csdn.net/">
                                  高校
                                  
                                </a>
                                
                              </li></ul>
                        </div>
                        <div class="toolbar-container-middle">
                          <div class="toolbar-search onlySearch"><div class="toolbar-search-container">
                    <input id="toolbar-search-input" autocomplete="off" type="text" value="" placeholder="spring源码解读">
                    <button id="toolbar-search-button"></button>
                    <input type="password" autocomplete="new-password" readonly="" disabled="true" style="display: none; position:absolute;left:-9999999px;width:0;height:0;">
                  </div></div>
                        </div>
                        <div class="toolbar-container-right">
                          <div class="toolbar-btns onlyUser"><div class="toolbar-btn toolbar-btn-login csdn-toolbar-fl toolbar-subMenu-box">
                      <a class="hasAvatar" data-report-click="{&quot;spm&quot;: &quot;3001.5343&quot;}" data-report-query="spm=3001.5343" href="https://blog.csdn.net/WGTCSDN"><img src="https://profile.csdnimg.cn/A/D/A/2_wgtcsdn"></a>
                      <div id="csdn-toolbar-profile" class="csdn-toolbar-plugin">
            <div class="csdn-profile-top">
              <a class="csdn-profile-avatar" data-report-click="{&quot;spm&quot;: &quot;3001.5343&quot;}" data-report-query="spm=3001.5343" href="https://blog.csdn.net/WGTCSDN"><img src="https://profile.csdnimg.cn/A/D/A/0_wgtcsdn"></a>
              <p class="csdn-profile-nickName">_winfield</p>
              <a data-report-click="{&quot;spm&quot;: &quot;3001.5344&quot;}" data-report-query="spm=3001.5344" href="https://mall.csdn.net/vip" class="csdn-profile-no-vip"></a>
            </div>
            <div class="csdn-profile-mid">
              <a data-report-click="{&quot;spm&quot;: &quot;3001.5347&quot;}" data-report-query="spm=3001.5347" href="https://blog.csdn.net/WGTCSDN?type=sub&amp;subType=fans"><i class="csdn-profile-fansCount">1</i>粉丝</a>
              <a data-report-click="{&quot;spm&quot;: &quot;3001.5348&quot;}" data-report-query="spm=3001.5348" href="https://blog.csdn.net/WGTCSDN?type=sub"><i class="csdn-profile-followCount">7</i>关注</a>
              <a data-report-click="{&quot;spm&quot;: &quot;3001.5349&quot;}" data-report-query="spm=3001.5349" href="https://blog.csdn.net/WGTCSDN"><i class="csdn-profile-likeCount">--</i>获赞</a>
            </div>
            <div class="csdn-profile-bottom">
              <ul class="csdn-border-bottom">
                <li class=""><a href="https://i.csdn.net/#/user-center/profile" data-report-click="{&quot;dest&quot;:&quot;https://i.csdn.net/#/user-center/profile&quot;,&quot;spm&quot;:&quot;3001.5111&quot;}" data-report-query="spm=3001.5111"><i class="csdn-profile-icon csdn-profile-icon-person"></i>个人中心</a></li><li class=""><a href="https://mp.csdn.net/console/article" data-report-click="{&quot;dest&quot;:&quot;https://mp.csdn.net/console/article&quot;,&quot;spm&quot;:&quot;3001.5448&quot;}" data-report-query="spm=3001.5448"><i class="csdn-profile-icon csdn-profile-icon-pages"></i>内容管理</a></li><li class=""><a href="https://edu.csdn.net/" data-report-click="{&quot;dest&quot;:&quot;https://edu.csdn.net/&quot;,&quot;spm&quot;:&quot;3001.5350&quot;}" data-report-query="spm=3001.5350"><i class="csdn-profile-icon csdn-profile-icon-study"></i>学习平台</a></li><li class=""><a href="https://mall.csdn.net/myorder" data-report-click="{&quot;dest&quot;:&quot;https://mall.csdn.net/myorder&quot;,&quot;spm&quot;:&quot;3001.5137&quot;}" data-report-query="spm=3001.5137"><i class="csdn-profile-icon csdn-profile-icon-order"></i>我的订单</a></li><li class="pb-8 csdn-border-bottom"><a href="https://i.csdn.net/#/wallet/index" data-report-click="{&quot;dest&quot;:&quot;https://i.csdn.net/#/wallet/index&quot;,&quot;spm&quot;:&quot;3001.5136&quot;}" data-report-query="spm=3001.5136"><i class="csdn-profile-icon csdn-profile-icon-wallet"></i>我的钱包</a></li><li class="pt-8 pb-8 csdn-border-bottom"><a href="https://i.csdn.net/#/uc/reward" data-report-click="{&quot;dest&quot;:&quot;https://i.csdn.net/#/uc/reward&quot;,&quot;spm&quot;:&quot;3001.5351&quot;}" data-report-query="spm=3001.5351"><i class="csdn-profile-icon csdn-profile-icon-draw"></i>签到抽奖</a></li><li class="pt-8 csdn-profile-logout"><a href="javascript:;" data-report-click="{&quot;spm&quot;:&quot;3001.5139&quot;}" data-report-query="spm=3001.5139"><i class="csdn-profile-icon csdn-profile-icon-logout"></i>退出</a></li>
              </ul>
            </div>
          </div></div>
                    <div class="toolbar-btn toolbar-btn-vip csdn-toolbar-fl">
                      <a data-report-click="{&quot;mod&quot;:&quot;popu_336&quot;,&quot;dest&quot;:&quot;https://mall.csdn.net/vip&quot;,&quot;spm&quot;:&quot;3001.4496&quot;}" data-report-query="spm=3001.4496" href="https://mall.csdn.net/vip">会员中心 </a>
                    <div id="csdn-plugin-vip" style="display: none;">
                        <div class="csdn-plugin-vip-header">
                            会员特权
                        </div>
                        <div class="csdn-plugin-vip-body">
                            <a href="https://download.csdn.net/?utm_source=vip_xz_862637798_yy"><i class="csdn-plugin-vip-icon csdn-plugin-vip-icon-download"></i><br>资源下载</a>
                            <a href="https://edu.csdn.net/course?channelType=3&amp;utm_source=vip_jpk_862637798_yy"><i class="csdn-plugin-vip-icon csdn-plugin-vip-icon-class"></i><br>千节精品课</a>
                            <a href="https://book.csdn.net/?utm_source=vip_dzs_862637798_yy"><i class="csdn-plugin-vip-icon csdn-plugin-vip-icon-book"></i><br>千本电子书</a>
                            <a href="https://so.csdn.net/so/search?q=&amp;t=vip&amp;s=0&amp;pnt=-1&amp;ct=100&amp;utm_source=vip_jswz_862637798_yy"><i class="csdn-plugin-vip-icon csdn-plugin-vip-icon-pages"></i><br>VIP技术文章</a>
                        </div>
                        <div class="csdn-plugin-vip-footer">
                            <a data-report-click="{&quot;spm&quot;: &quot;3001.5400&quot;}" data-report-query="spm=3001.5400" class="csdn-plugin-vip-footer-btn" href="https://mall.csdn.net/vip">
                              开通会员
                            </a>
                            <a data-report-click="{&quot;spm&quot;: &quot;3001.5401&quot;}" data-report-query="spm=3001.5401" class="csdn-plugin-vip-footer-link" href="https://www.csdn.net/vip">
                              查看完整会员权益<i></i>
                            </a>
                        </div>
                    </div></div>
                    <div class="toolbar-btn toolbar-btn-collect csdn-toolbar-fl">
                      <a data-report-click="{&quot;spm&quot;:&quot;3001.4506&quot;}" data-report-query="spm=3001.4506" href="https://i.csdn.net/#/user-center/collection-list?type=1">收藏</a>
                    
          <div id="csdn-toolbar-collection" class="csdn-toolbar-plugin" style="display: none;">
            <div class="toolbar-collection-left csdn-toolbar-scroll-box">
              <ul>
          <li class="collection-folder-active">
            <div class="toolbar-collection-folder-name">java文档1</div>
            <div class="toolbar-collection-folder-count">6</div>
          </li>
        
          <li>
            <div class="toolbar-collection-folder-name">默认收藏夹</div>
            <div class="toolbar-collection-folder-count">9</div>
          </li>
        </ul>
            </div>
            <div class="toolbar-collection-right">
              <ul class="csdn-toolbar-scroll-box">
          <li>
            <a href="https://blog.csdn.net/luoyang_java/article/details/112602640" target="_blank">
              <span class="toolbar-collection-type">博客</span>
              <span class="toolbar-collection-title">为什么要学习源码?架构师告诉你原因</span>
            </a>
          </li>
        
          <li>
            <a href="https://blog.csdn.net/javarrr/article/details/89472495" target="_blank">
              <span class="toolbar-collection-type">博客</span>
              <span class="toolbar-collection-title">SpringBoot启动原理及相关流程</span>
            </a>
          </li>
        
          <li>
            <a href="https://blog.csdn.net/weixin_41846320/article/details/82697818" target="_blank">
              <span class="toolbar-collection-type">博客</span>
              <span class="toolbar-collection-title">IntelliJ Idea 常用11款插件(提高开发效率),附优秀主题插件</span>
            </a>
          </li>
        
          <li>
            <a href="https://blog.csdn.net/f641385712/article/details/105610114" target="_blank">
              <span class="toolbar-collection-type">博客</span>
              <span class="toolbar-collection-title">Netflix OSS套件一站式学习驿站</span>
            </a>
          </li>
        
          <li>
            <a href="https://blog.csdn.net/f641385712/article/details/105762050" target="_blank">
              <span class="toolbar-collection-type">博客</span>
              <span class="toolbar-collection-title">不懂SpringApplication生命周期事件?那就等于不会Spring Boot嘛</span>
            </a>
          </li>
        
          <li>
            <a href="https://blog.csdn.net/f641385712/article/details/103732359" target="_blank">
              <span class="toolbar-collection-type">博客</span>
              <span class="toolbar-collection-title">[享学Jackson] 一、初识Jackson -- 世界上最好的JSON库</span>
            </a>
          </li>
        </ul>
            </div>
            <div class="csdn-toolbar-plugin-triangle"></div>
          </div>
        </div>
                     <div class="toolbar-btn csdn-toolbar-fl"><a data-report-click="{&quot;spm&quot;:&quot;3001.4507&quot;}" data-report-query="spm=3001.4507" href="https://blog.csdn.net/nav/watchers">动态</a></div>
                    <div class="toolbar-btn toolbar-btn-msg csdn-toolbar-fl">
                      <div class="toolbar-subMenu-box">
                        <a data-report-click="{&quot;spm&quot;:&quot;3001.4508&quot;}" data-report-query="spm=3001.4508" id="toolbar-remind" href="https://i.csdn.net/#/msg/index"><span class="pos-rel">消息</span></a>
                      <div class="toolbar-subMenu">
                    <a id="toolbar-announcement" href="https://blog.csdn.net/blogdevteam/article/details/112280974?utm_source=gonggao_0107"><span class="pos-rel">公告</span></a>
                    <a data-type="comment" href="https://i.csdn.net/#/msg/index"><span class="pos-rel">评论</span></a>
                                      <a data-type="attention" href="https://i.csdn.net/#/msg/attention"><span class="pos-rel">关注</span></a>         
                                      <a data-type="like" href="https://i.csdn.net/#/msg/like"><span class="pos-rel">点赞</span></a>
                                      <a data-type="chat" href="https://im.csdn.net/im/main.html"><span class="pos-rel">私信</span></a>
                                      <a data-type="answer" href="https://i.csdn.net/#/msg/answer"><span class="pos-rel">回答</span></a>
                                      <a data-type="notice" href="https://i.csdn.net/#/msg/notice"><span class="pos-rel">系统通知</span></a>
                                      <a href="https://i.csdn.net/#/msg/setting">消息设置</a>     
                  </div></div>
                      <div class="toolbar-msg-box"></div>
                    </div>
                    <div class="toolbar-btn toolbar-btn-write csdn-toolbar-fl toolbar-subMenu-box">
                      <a data-report-click="{&quot;spm&quot;:&quot;3001.4503&quot;}" data-report-query="spm=3001.4503" href="https://mp.csdn.net"><i></i>创作中心</a>
                    
        <div id="csdn-toolbar-write" class="csdn-toolbar-plugin" style="display: none;">
          <div class="csdn-toolbar-plugin-triangle"></div>
          <ul class="csdn-toolbar-write-box">
            <li class="csdn-toolbar-write-box-blog">
              <a href="https://mp.csdn.net/editor/html" target="_blank" data-report-click="{&quot;spm&quot;:&quot;3001.5352&quot;}" data-report-query="spm=3001.5352">
                <i class="csdn-toolbar-write-icon"></i>
                <span>写文章</span>
              </a>
            </li>
            <li class="csdn-toolbar-write-box-blink">
              <a href="https://blink.csdn.net" target="_blank" data-report-click="{&quot;spm&quot;:&quot;3001.5353&quot;}" data-report-query="spm=3001.5353">
                <i class="csdn-toolbar-write-icon"></i>
                <span>发Blink</span>
              </a>
            </li>
            <li class="csdn-toolbar-write-box-ask">
              <a href="https://ask.csdn.net/?word=" target="_blank" data-report-click="{&quot;spm&quot;:&quot;3001.5354&quot;}" data-report-query="spm=3001.5354">
                <i class="csdn-toolbar-write-icon"></i>
                <span>提问题</span>
              </a>
            </li>
            <li class="csdn-toolbar-write-box-upload">
              <a href="https://mp.csdn.net/console/uploadResources" target="_blank" data-report-click="{&quot;spm&quot;:&quot;3001.5355&quot;}" data-report-query="spm=3001.5355">
                <i class="csdn-toolbar-write-icon"></i>
                <span>传资源</span>
              </a>
            </li>
            <li class="csdn-toolbar-write-box-code">
              <a href="https://codechina.csdn.net/explore" target="_blank" data-report-click="{&quot;spm&quot;:&quot;3001.5356&quot;}" data-report-query="spm=3001.5356">
                <i class="csdn-toolbar-write-icon"></i>
                <span>建项目</span>
              </a>
            </li>
          </ul>
        
        <div class="csdn-toolbar-write-activity">
          <div class="csdn-toolbar-write-activity-head">创作活动</div>
          <ul>
          <li>
            <a href="https://marketing.csdn.net/p/c7a5d45d39ce3d63845f97a29f74fb28" target="_blank">#新星计划报名了!下个SuperStar就是你</a>
          </li>
        
          <li>
            <a href="https://marketing.csdn.net/p/55d59e00e66e4d3796149b096ae7c810" target="_blank">#原力计划【精英季】开启报名,各路英豪更待何时?</a>
          </li>
        
          <li>
            <a href="https://marketing.csdn.net/p/15940c87f66c68188cfe5228cf4a0c3f" target="_blank">#100%有奖 | ”我的Serverless 实战“ 征稿活动</a>
          </li>
        
          <li>
            <a href="https://marketing.csdn.net/p/540279e862dce1fe1f57b7d9f9c6b39c" target="_blank">#万元奖金,百万流量!CSDN 红人计划开启报名</a>
          </li>
        </ul>
          <div class="toolbar-write-activity-more">
            <a href="https://mp.csdn.net/console/creative" target="_blank" data-report-click="{&quot;spm&quot;:&quot;3001.5358&quot;}" data-report-query="spm=3001.5358">查看更多<i></i></a>
          </div>
        </div>
      </div>
      </div></div>
                        </div>
                      </div>
                    </div>
                  </div>
        <script>
            var toolbarSearchExt = '{"landingWord":["spring事务底层实现原理"],"queryWord":"","tag":["事务","spring事务","spring源码解读","源码"],"title":"spring事务从底层掌握其实现原理"}';
        </script>
    <script src="https://g.csdnimg.cn/common/csdn-toolbar/csdn-toolbar.js" type="text/javascript"></script>
    <script>
    (function(){
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        }
        else {
            bp.src = 'http://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
    </script>
    

spring事务从底层掌握其实现原理

流程介绍

主流程介绍

众所周知,Spring事务采用AOP的方式实现,我们从TransactionAspectSupport这个类开始分析。

  1. 获取事务的属性(@Transactional注解中的配置)
  2. 加载配置中的TransactionManager.
  3. 获取收集事务信息TransactionInfo
  4. 执行目标方法
  5. 出现异常,尝试处理。
  6. 清理事务相关信息
  7. 提交事务
//1. 获取@Transactional注解的相关参数
TransactionAttributeSource tas = getTransactionAttributeSource();
// 2. 获取事务管理器
	final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
	final PlatformTransactionManager tm = determineTransactionManager(txAttr);
	final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
	// Standard transaction demarcation with getTransaction and commit/rollback calls.
	// 3. 获取TransactionInfo,包含了tm和TransactionStatus
	TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
	Object retVal = null;
	try {
		// This is an around advice: Invoke the next interceptor in the chain.
		// This will normally result in a target object being invoked.
		// 4.执行目标方法
		retVal = invocation.proceedWithInvocation();
	}
	catch (Throwable ex) {
	   //5.回滚
		// target invocation exception
		completeTransactionAfterThrowing(txInfo, ex);
		throw ex;
	}
	finally {
	  // 6. 清理当前线程的事务相关信息
		cleanupTransactionInfo(txInfo);
	}
	// 提交事务
	commitTransactionAfterReturning(txInfo);
	return retVal;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

doBegin做了什么

在执行createTransactionIfNecessary获取事务状态时,就准备好了开启事务的所有内容,主要是执行了JDBC的con.setAutoCommit(false)方法。同时处理了很多和数据库连接相关的ThreadLocal变量。

关键对象介绍

PlatformTransactionManager

TransactionManager是做什么的?它保存着当前的数据源连接,对外提供对该数据源的事务提交回滚操作接口,同时实现了事务相关操作的方法。一个数据源DataSource需要一个事务管理器。

属性:DataSource

内部核心方法:
public commit 提交事务
public rollback 回滚事务
public getTransaction 获得当前事务状态

protected doSuspend 挂起事务

protected doBegin 开始事务,主要是执行了JDBC的con.setAutoCommit(false)方法。同时处理了很多和数据库连接相关的ThreadLocal变量。

protected doCommit 提交事务
protected doRollback 回滚事务
protected doGetTransaction() 获取事务信息
final getTransaction 获取事务状态

获取对应的TransactionManager

@Nullable
	protected PlatformTransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
		// Do not attempt to lookup tx manager if no tx attributes are set
		if (txAttr == null || this.beanFactory == null) {
			return getTransactionManager();
		}
	String qualifier = txAttr.getQualifier();
	//如果指定了Bean则取指定的PlatformTransactionManager类型的Bean
	if (StringUtils.hasText(qualifier)) {
		return determineQualifiedTransactionManager(this.beanFactory, qualifier);
	}
	//如果指定了Bean的名称,则根据bean名称获取对应的bean
	else if (StringUtils.hasText(this.transactionManagerBeanName)) {
		return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
	}
	else {
	// 默认取一个PlatformTransactionManager类型的Bean
		PlatformTransactionManager defaultTransactionManager = getTransactionManager();
		if (defaultTransactionManager == null) {
			defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
			if (defaultTransactionManager == null) {
				defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class);
				this.transactionManagerCache.putIfAbsent(
						DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
			}
		}
		return defaultTransactionManager;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

可以看到,如果没有指定TransactionManager参数的话,会使用默认的一个实现,所以当程序中有多个数据库时,事务执行最好是指定事务管理器。

事务的信息TransactionInfo

TransactionInfo是对当前事务的描述,其中记录了事务的状态等信息。它记录了和一个事务所有的相关信息。它没有什么方法,只是对事务相关对象的一个组合。最关键的对象是TransactionStatus,它代表当前正在运行的是哪个事务。

1.核心属性:事务状态TransactionStatus
2.事务管理器
3.事务属性
4.上一个事务信息oldTransactionInfo,REQUIRE_NEW传播级别时,事务挂起后前一个事务的事务信息
在这里插入图片描述

当前事务状态TransactionStatus

通过TransactionManager的getTransaction方法,获取当前事务的状态。
具体是在AbstractPlatformTransactionManager中实现.
TransactionStatus被用来做什么:TransactionManager对事务进行提交或回滚时需要用到该对象
具体方法有:
在这里插入图片描述
作用:

  1. 判断当前事务是否是一个新的事务,否则加入到一个已经存在的事务中。事务传播级别REQUIRED和REQUIRE_NEW有用到。

  2. 当前事务是否携带保存点,嵌套事务用到。setRollbackOnly,isRollbackOnly,当子事务回滚时,并不真正回滚事务,而是对子事务设置一个标志位。

  3. 事务是否已经完成,已经提交或者已经回滚。

传播级别

介绍

Spring事务的传播级别描述的是多个使用了@Transactional注解的方法互相调用时,Spring对事务的处理。包涵的传播级别有:

1、REQUIRED, 如果当前线程已经在一个事务中,则加入该事务,否则新建一个事务。
2、SUPPORT, 如果当前线程已经在一个事务中,则加入该事务,否则不使用事务。
3、MANDATORY(强制的),如果当前线程已经在一个事务中,则加入该事务,否则抛出异常。
4、REQUIRES_NEW,无论如何都会创建一个新的事务,如果当前线程已经在一个事务中,则挂起当前事务,创建一个新的事务。
5、NOT_SUPPORTED,如果当前线程在一个事务中,则挂起事务。
6、NEVER,如果当前线程在一个事务中则抛出异常。
7、NESTED, 执行一个嵌套事务,有点像REQUIRED,但是有些区别,在Mysql中是采用SAVEPOINT来实现的。

挂起事务,指的是将当前事务的属性如事务名称,隔离级别等属性保存在一个变量中,同时将当前线程中所有和事务相关的ThreadLocal变量设置为从未开启过线程一样。Spring维护着一个当前线程的事务状态,用来判断当前线程是否在一个事务中以及在一个什么样的事务中,挂起事务后,当前线程的事务状态就好像没有事务。

现象描述

@Service
public class MyTsA {
    @Resource
    private UserServiceImpl userService;
    @Resource
    private MyTsB myTsB;
@Transactional(rollbackFor = Exception.class)
public void testNewRollback(){
    User user = new User();
    user.setId(1);
    user.setName("张三");
    userService.save(user);
    myTsB.save();
}

}

@Service
public class MyTsB {
@Resource
private UserServiceImpl userService;
@Transactional(rollbackFor = RuntimeException.class, propagation = ???)
public void save(){
User user = new User();
user.setId(2);
user.setName(“李四”)
userService.save(user);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

如上面所示有两个事务A和事务B,事务A方法中调用了事务B方法,区分两种回滚情况。
A提交,B回滚。
A回滚,B提交。

对于不同的传播级别:
1.当传播级别为为REQUIRED时,第一种情况A和B都会回滚。
2.。当传播级别为RQUIRED_NEW时,第一种情况A可以成功提交,B回滚,第二种情况A回滚,B可以正确提交,二者互不影响。(在A事务捕获B事务异常的情况下,保证A事务提交)
3.当传播级别为NESTED时,第一种情况A可以正常提交,B回滚,第二种情况二者都会回滚。

原理

我们从两个角度看他们的实现原理,一个是刚进入事务时,针对不同的传播级别,它们的行为有什么区别。另一个角度是当事务提交或者回滚时,传播级别对事务行为的影响。

首先在尝试获取事务信息时,如果当前已经存在一个事务,则会根据传播级别做一些处理:

隔离级别对开始事务的影响(获取TransactionStatus)

@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
  // 从当前的transactionManager获取DataSource对象
  // 然后以该DataSource对象为Key,
  // 去一个ThreadLocal变量中的map中获取该DataSource的连接
  // 然后设置到DataSourceTransactionObject中返回。
	Object transaction = doGetTransaction();
	// Cache debug flag to avoid repeated checks.
	boolean debugEnabled = logger.isDebugEnabled();
	if (definition == null) {
		// Use defaults if no transaction definition given.
		definition = new DefaultTransactionDefinition();
	}
// 如果当前线程已经在一个事务中了,则需要根据事务的传播级别
//来决定如何处理并获取事务状态对象
	if (isExistingTransaction(transaction)) {
		// Existing transaction found -> check propagation behavior to find out how to behave.
		return handleExistingTransaction(definition, transaction, debugEnabled);
	}
	// Check definition settings for new transaction.
	if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
		throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
	}
	// No existing transaction found -> check propagation behavior to find out how to proceed.
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
		throw new IllegalTransactionStateException(
				"No existing transaction found for transaction marked with propagation 'mandatory'");
	}
	else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
			definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
			definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
		SuspendedResourcesHolder suspendedResources = suspend(null);
		if (debugEnabled) {
			logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
		}
		try {
		  //如果当前不在一个事务中,则执行事务的准备操作
			boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
			// 构造事务状态对象,注意这里第三个参数为true,代表是一个新事务
			DefaultTransactionStatus status = newTransactionStatus(
					definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
			//执行begin操作,核心操作是设置隔离级别,执行   conn.setAutoCommit(false); 同时将数据连接绑定到当前线程
			doBegin(transaction, definition);
			// 针对事务相关属性如隔离级别,是否在事务中,设置绑定到当前线程
			prepareSynchronization(status, definition);
			return status;
		}
		catch (RuntimeException | Error ex) {
			resume(null, suspendedResources);
			throw ex;
		}
	}
	else {
		// Create "empty" transaction: no actual transaction, but potentially synchronization.
		if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
			logger.warn("Custom isolation level specified but no actual transaction initiated; " +
					"isolation level will effectively be ignored: " + definition);
		}
		boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
		return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
	}
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

可以看到,如果当前不存在事务时,创建一个新的TransactionStatus对象,否则进入到handleExistingTransaction。下面来看这个方法

1.如果是NEVER传播级别则抛出异常
2. 如果是不支持,则挂起事务,将当前事务对象设置为null,newTransaction设置为false,把线程的相关Threadlocal变量改的就像当前不存在事务一样
3. 如果是required_NEW的话,则挂起当前事务,同时创建一个新的事务,执行doBegin操作,设置newTransaction为true
4.如果是嵌入事务,则创建一个SAVEPOINT
5.对于REQUIRED传播级别会把newTransaction标志位设置为false

/**
 * Create a TransactionStatus for an existing transaction.
 */
private TransactionStatus handleExistingTransaction(
		TransactionDefinition definition, Object transaction, boolean debugEnabled)
		throws TransactionException {
    //如果是NEVER传播级别则抛出异常
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
		throw new IllegalTransactionStateException(
				"Existing transaction found for transaction marked with propagation 'never'");
	}
    // 如果是不支持,则挂起事务
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
		if (debugEnabled) {
			logger.debug("Suspending current transaction");
		}
		Object suspendedResources = suspend(transaction);
		boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
		//挂起事务同时将当前事务设置为null,newTransaction设置为false,把线程的相关Threadlocal变量改的就像当前不存在事务一样
		return prepareTransactionStatus(
				definition, null, false, newSynchronization, debugEnabled, suspendedResources);
	}
    //如果是required_NEW的话,则挂起当前事务,同时创建一个新的事务,执行doBegin操作
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
		if (debugEnabled) {
			logger.debug("Suspending current transaction, creating new transaction with name [" +
					definition.getName() + "]");
		}
		SuspendedResourcesHolder suspendedResources = suspend(transaction);
		try {
			boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
			DefaultTransactionStatus status = newTransactionStatus(
					definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
			doBegin(transaction, definition);
			prepareSynchronization(status, definition);
			return status;
		}
		catch (RuntimeException | Error beginEx) {
			resumeAfterBeginException(transaction, suspendedResources, beginEx);
			throw beginEx;
		}
	}
    // 如果是嵌入事务,则创建一个SAVEPOINT
	if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
		if (!isNestedTransactionAllowed()) {
			throw new NestedTransactionNotSupportedException(
					"Transaction manager does not allow nested transactions by default - " +
					"specify 'nestedTransactionAllowed' property with value 'true'");
		}
		if (debugEnabled) {
			logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
		}
		if (useSavepointForNestedTransaction()) {
			// Create savepoint within existing Spring-managed transaction,
			// through the SavepointManager API implemented by TransactionStatus.
			// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
			DefaultTransactionStatus status =
					prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
			status.createAndHoldSavepoint();
			return status;
		}
		else {
			// Nested transaction through nested begin and commit/rollback calls.
			// Usually only for JTA: Spring synchronization might get activated here
			// in case of a pre-existing JTA transaction.
			boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
			DefaultTransactionStatus status = newTransactionStatus(
					definition, transaction, true, newSynchronization, debugEnabled, null);
			doBegin(transaction, definition);
			prepareSynchronization(status, definition);
			return status;
		}
	}
// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
if (debugEnabled) {
	logger.debug("Participating in existing transaction");
}

//这里判断是否需要对已经存在的事务进行校验,这个可以通过AbstractPlatformTransactionManager.setValidateExistingTransaction(boolean)来设置,设置为true后需要校验当前事务的隔离级别和已经存在的事务的隔离级别是否一致
if (isValidateExistingTransaction()) {
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
Constants isoConstants = DefaultTransactionDefinition.constants;
throw new IllegalTransactionStateException(“Participating transaction with definition [” +
definition + "] specifies isolation level which is incompatible with existing transaction: " +
(currentIsolationLevel != null ?
isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
“(unknown)”));
}
}
if (!definition.isReadOnly()) {
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
throw new IllegalTransactionStateException(“Participating transaction with definition [” +
definition + “] is not marked as read-only but existing transaction is”);
}
}
}
// 如果不设置是否校验已经存在的事务,则对于REQUIRED传播级别会走到这里来,这里把newTransaction标志位设置为false,
// 这里用的definition是当前事务的相关属性,所以隔离级别等依然是当前事务的(子事务),而不是已经存在的事务的隔离级别(父事务)
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103

隔离级别对回滚事务的影响

1、如果newTransaction设置为ture,则真正执行回滚。
2、如果有保存点,则回滚到保存点。
3、否则不会真正回滚,而是设置回滚标志位。

private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
		try {
			boolean unexpectedRollback = unexpected;
			try {
				triggerBeforeCompletion(status);
				// 如果有保存点
				if (status.hasSavepoint()) {
					if (status.isDebug()) {
						logger.debug("Rolling back transaction to savepoint");
					}
					status.rollbackToHeldSavepoint();
				}
				// 如果是新的事务,当传播级别为RUQUIRED_NEW时会走到这里来
				else if (status.isNewTransaction()) {
					if (status.isDebug()) {
						logger.debug("Initiating transaction rollback");
					}
					doRollback(status);
				}
				else {
				    // 加入到事务中,设置回滚状态,适用于REQUIRED传播级别
				    // 并不会真的回滚,而是设置回滚标志位
					// Participating in larger transaction
					if (status.hasTransaction()) {
						if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
							if (status.isDebug()) {
								logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
							}
							doSetRollbackOnly(status);
						}
						else {
							if (status.isDebug()) {
								logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
							}
						}
					}
					else {
						logger.debug("Should roll back transaction but cannot - no transaction available");
					}
					// Unexpected rollback only matters here if we're asked to fail early
					if (!isFailEarlyOnGlobalRollbackOnly()) {
						unexpectedRollback = false;
					}
				}
			}
			catch (RuntimeException | Error ex) {
				triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
				throw ex;
			}
		triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);

		// Raise UnexpectedRollbackException if we had a global rollback-only marker
		if (unexpectedRollback) {
			throw new UnexpectedRollbackException(
					"Transaction rolled back because it has been marked as rollback-only");
		}
	}
	finally {
		cleanupAfterCompletion(status);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

隔离级别对提交事务的影响

1、就算事务方法没有抛出异常,走到了commit方法中,但是依然有可能回滚事务。
2、对于REQUIRED传播级别,即使父事务中没有抛出异常,但是子事务中已经设置了回滚标志,那么父事务依然会回滚
3、只有newTransaction标志位为true的事务才会真正执行commit操作。

@Override
public final void commit(TransactionStatus status) throws TransactionException {
	if (status.isCompleted()) {
		throw new IllegalTransactionStateException(
				"Transaction is already completed - do not call commit or rollback more than once per transaction");
	}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
if (defStatus.isLocalRollbackOnly()) {
	if (defStatus.isDebug()) {
		logger.debug("Transactional code has requested rollback");
	}
	processRollback(defStatus, false);
	return;
}

// 对于REQUIRED传播级别,即使父事务中没有抛出异常,但是子事务中已经设置了回滚标志,那么父事务依然会回滚
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug(“Global transaction is marked as rollback-only but transactional code requested commit”);
}
processRollback(defStatus, true);
return;
}

processCommit(defStatus);

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

在这里插入图片描述

为什么我的事务不生效

1.如果不是Innodb存储引擎,MyISAM不支持事务。
2.没有指定rollbackFor参数。
3. 没有指定transactionManager参数,默认的transactionManager并不是我期望的,以及一个事务中涉及到了多个数据库。
4. 如果AOP使用了JDK动态代理,对象内部方法互相调用不会被Spring的AOP拦截,@Transactional注解无效。
5. 如果AOP使用了CGLIB代理,事务方法或者类不是public,无法被外部包访问到,或者是final无法继承,@transactional注解无效。

  • 点赞 2
  • 评论
  • 分享
    x

    海报分享

    扫一扫,分享海报

  • 收藏 8
  • 打赏

    打赏

    落阳Java_詹哥

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

    C币 余额
    ¥2 ¥4 ¥6 ¥10 ¥20 ¥50

    您的余额不足,请先充值哦~去充值

  • 举报
  • 关注
  • 一键三连

Spring 事务 实现原理源码分析流程介绍主流程关键对象介绍PlatformTransactionManager获取对应的TransactionManager 事务的信息TransactionInfo当前 事务状态TransactionStatus传播对象 实现原理隔离级别对开始 事务的影响(获取TransactionStatus)隔离级别对回滚 事务的影响隔离级别对提交 事务的影响 流程介绍

获取事务的属…


事务 相信大家都在ATM机取过钱,但是是否有人考虑过它的流程是怎样的呢? 我们都知道,假如我们取300块钱,那么当这三百块钱 ATM机出来时,我们的账户相应的会减少300。这两个过程一定是要同时成功才算成功的。否则就会出现账户少了300.但是钱没出来,对于我们来说,我们损失了300.而如果钱出来了但是账户钱没扣掉的话,银行就会损失300.这两种情况都是不可取的。所以就需要保证要么大家一起成功,有一...
表情包
插入表情
还能输入1000个字符
相关推荐
Spring 事务@Transactional 底层原理_好奇心森林的博客
5-7
开发中少不了用到 事务注解@Transactional来管理 事务,@Transactional注解 底层是基于 Spring AOP来进行实现的。 我们来看两个典型的AOP应用场景: 统一的验证用户逻辑 反复使用的开启 事务,关闭 事务逻辑 ...
Spring事务底层工作原理_1
4-30
所以ProxyTransactionManagementConfiguration的作用就是向 Spring容器中添加了一个Advisor,有了Advisor,那么 Spring在构造bean时就会查看当前bean是不是匹配所设置的PointCut(也就是beanClass上是否有@Transactional注解或beanClass中某个方法上是否有...

事务,大家所熟悉的事务(Transaction),基本上会就往Spring事务靠。Spring事务管理基于底层数据库本身的事务处理机制。数据库事务的基础,是掌握Spring事务管理的基础。这篇总结下Spring事务

事务具备ACID四种特性,ACID是Atomic(原子性)、Consistency(一致性)、Isolation(隔离性)和Durability


背景:最近的项目中需要用到 Spring事务管理相关的知识,以前也了解过 Spring事务管理,但是仅仅止步于会用,这一次借着这次机会,深入 源码分析一下 Spring是如何实现 事务的。

前面已经有一篇文章讲过了如何在Spring中使用声明式事务,并对一些特性进行了讲解,具体如下:Spring事务管理-使用基础

这一篇文章SpringBoot启动出发,到Spring实现事务管理,源码角度,分


spring 事务-说说Propagation及 实现原理_yanyan198805...
5-7
跨多种 底层数据层,如jdbc,mybatis,hibernate,jta,难以统一编码方式。 spring提供了声明式 事务,使得我们不用关注 底层的具体实现,屏蔽了多种不同的 底层实现细节,为了支持多种复杂业务对 事务的精细控制, spring提供了 事务的传播属性,结合声明式...
一文带你深入理解 Spring 事务原理_程序员小乐
5-4
Spring 事务的基本原理 Spring 事务的本质 实就是数据库对 事务的支持,没有数据库的 事务支持, spring是无法提供 事务功能的。对于纯JDBC操作数据库,想要用到 事务,可以按照以下步骤进行: 获取连接 Connection con = DriverManager.getConnection()...
Spring AOP的 底层实现技术三、 Spring AOP的实现我们来试着看看能不能理解 SpringAOP 底层实现原理。3.1 Spring AOP的几个概念 Spring AOP中的几个基本概念,每次学习AOP都被这几个概念折腾的很不爽,我们在这里再把这几个概念描述一遍,力争把这几个概念搞清,在每次review这块内容的时候可以很快上手。1.切面(Aspect):切面就是一个关注点的模块化,如事...
本博客分为两点,一个是 spring 事务 实现原理 源码 解读(个人能力,初步 解读),二是 spring 事务的传播属性

 

简单案例,保存订单,修改商品数量

就是这两个方法,第一个方法中引用了第二个方法,都用@Transactional注解。debug调用shopping方法。

 

spring事务实现的源码

在调用方法时会扫描@Transactional,进入方法前会判断是否有注解(在…


对于一个应用而言, 事务的使用基本是不可避免的。虽然 Spring给我们提供了开箱即用的 事务功能——@Transactional。 但是,自带的 事务功能却也存在控制粒度不够的缺点。更糟糕的是,@Transactional在某些情况下就失效了。可能一些读者baidu/google一下解决办法后,失效的问题确实解决了。但是由于不了解 底层的原理,这样的问题可能在今后的工作中往复出现。 本文就为大家揭开@Transactional下的秘密。

原生的事务管理

在没有Spring存在的时候,事务就已经诞生了…


一、数据库的 事务的基本特性

事务是区分文件存储系统与Nosql数据库重要特性之一,存在的意义是为了保证即使在并发情况下也能正确的执行crud操作。怎样才算是正确的呢?这时提出了事务需要保证的四个特性即ACID:

A: 原子性(atomicity)

事务中各…


spring 事务传播属性示例展示及原理简析。

Spring声明式事务让我们复杂的事务处理中得到解脱,使我们再也不用去处理这些步骤:获得连接、关闭连接、事务提交和回滚操作。再也不需要在事务相关方法中处理大量的try…catch…finally代码。
Spring事务的使用虽然已经相对简单的多,但是…


文章目录声明式 事务的概述声明式 事务的初探声明式 事务源码分析 声明式 事务的概述 Spring 的声明式 事务管理在 底层是建立在 AOP 的基础之上的。 本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个 事务,在执行完目标方法之后根据执行情况提交或者回滚 事务。 声明式 事务最大的优点就是不需要通过编程的方式管理 事务,这样就不需要在业务逻辑代码中掺杂 事务管理的代码,只需在配置文件中做相关的事...
MySQL 事务隔离 Ⅰ.四种隔离级别 1.读未提交 一个 事务还没提交时,它做的变更就能被别的 事务看到。 2.读已提交 一个 事务提交之后,它做的变更才会被 事务看到。 3.可重复读 一个 事务执行过程中看到的数据,总是跟这个 事务在启动时看到的数据是一致的。 当然在可重复读隔离级别下,未提交变更对 事务也是不可见的。 4.串行化 顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的 事务必须等前一个 事务执行完成,才能继续执行。 Ⅱ.隔离机制分析 读未提交 直接返回记
  前言:现今 SpringBoot、 SpringCloud技术非常火热,作为 Spring之上的框架,他们大量使用到了 Spring的一些 底层注解、原理,比如@Conditional、@Import、@EnableXXX等。如果 掌握这些 底层原理、注解,那么我们对这些高层框架就能做到高度定制,使用的游刃有余   本章内容: Spring声明式 事务的使用与 源码分析 一、环境搭建   1、导...
天天喊着微服务,微服务的,微服务怎么牛逼,微服务有多强大,学好微服务三天不用吃饭的那种?那我心里不禁一紧微服务到底是个啥?往下看!总有东西有点帮助!

先来个简单的介绍吧!

SpringCloud框架

针对这个架构图我分层介绍一下:

1、是web服务器的选型,这个我选择的是nginx+keepalived,haproxy也是一个选择,但是haproxy在反向代理处理跨域访问的时候问题很多…


1、 Spring事务处理的作用:  

Spring事务处理,是将事务处理的工作统一起来,并为事务处理提供通用的支持。

 
2、工作原理及实现

 
a、划分处理单元——IOC

 

由于spring解决的问题是对单个数据库进行局部事务处理的,具体的实现首相用spring中的IOC划分了事务处理单元。并且将对事务的各种配置放到了ioc容器中(设置事务管理器,设置事务


文章目录1.数据库的 事务的基本特性1.1 演示1.1.1 sql准备1.1.2 设置连接参数1.2 数据库默认隔离级别1.3 查看mysql 的默认隔离级别2. spring事务的支持与使用2.1 spring 事务相关API说明2.1.1 如何使用 spring 事务2.2.2 接口结构图2.2.3 API使用2.2 声明示事物2.2.1 如何使用2.2.1.1 添加依赖2.2.1.2 xml配置2...
事务是一种all or nothing的执行策略,常见数据库,这种策略遵 ACID原则,可以很好的保证业务的执行, spring 事务 底层可以使用tx命名空间实现,也可以通过Transactional注解的方式来实现,本文就讲下 spring transactional注解 底层的工作原理,要了解这个工作原理,首先要了解cglib的工作原理,这个可以参考文章:https://blog.csdn.net/j...

1.1 Spring Data Jpa底层原理解析

 目标:知道它是怎么运行的?底层到底封装的是谁?、
明确一点:我们所使用的所有框架,底层大多数都使用了动态代理技术、反射技术来封装实现。

 分析步骤:

我们只写了接口,但是没有写实现类,这个实现类就是Spring在运行的时候,注入的代理对象。
Spring怎么知道生成的那个dao的实现类?因为在配置文件中指定了dao接口所在的…


该套视频教程共包含16门课程,分别是Linux入门到精通、大型ERP项目实战教程、solr教程、Lucene教学视频、Java反射与注解开发、Hadoop大数据入门教程、Activiti工作流教程、redis高并发由浅入深、webservice入门教程、hibernate4入门教程、大型分布式redis+solr+Linux+nginx+ springmvc+mybatis电商项目、struts2深入浅出、oracle入门到大神、 springmvc深入浅出、 spring 3.2教程、mybatis入门到精通教程、Java EE教程、Mysql教程。
本课程讲述了c++的基本语言,进阶语言,以实战为基准,高效率传递干货, 教会学员命令行编译直击 底层过程,现场编码 并且 掌握各种排错思路
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页

最新评论

举报

选择你想要举报的内容(必选)
  • 内容涉黄
  • 政治相关
  • 内容抄袭
  • 涉嫌广告
  • 内容侵权
  • 侮辱谩骂
  • 样式问题
  • 其他
原文链接(必填)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值