在学习spring事务的时候,一定会涉及到一个概念,无法避免的,就是事务挂起和事务恢复
对于事务挂起和事务恢复,可以简单的描述一下,是这样的
1.首先我们假设有两个类,A类和B类,两个类中的字段是一模一样的,A类表示当前事务,B类表示备份事务
2.如果我开启一个事务,会把当前事务信息,存入到A类中,如果我这时候要进行事务挂起
3.事务挂起:就会把A类中当前事务的信息,赋值到B类中,然后在创建一个新事务的时候,会赋值到A类中
4.恢复事务:如果此时我当前事务执行完毕了,需要恢复原来的事务,就只需要将A类清空,然后将B类中的数据信息赋值到A类,此时A事务就会再次生效

我觉得可以理解为就是倒腾了一手

事务挂起源码

org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction
我们直接跳入到这个方法中来看,这个方法是在当前事务存在的时候,会进入到这个方法来处理,执行链路是这样的
org.springframework.transaction.interceptor.TransactionInterceptor#invokeorg.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransactionorg.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessaryorg.springframework.transaction.support.AbstractPlatformTransactionManager#getTransactionorg.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction

正常的话,一个事务方法的执行是这个链路,自己debug看下即可,但是要进入到这个方法中,有一个前提,就是当前事务已存在,然后又调用了另外一个事务方法,才会进入到这里
我们以PROPAGATION_REQUIRES_NEW这个级别的传播机制为例,为什么以这个为例,因为这个传播机制,在当前事务存在的时候,是会将当前事务挂起,然后开启一个新的事务,也正好可以看下spring是如何挂起事务,并创建新事务的


if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {if (debugEnabled) {logger.debug("Suspending current transaction, creating new transaction with name [" +definition.getName() + "]");}/*** 这里是挂起事务的操作,挂起事务的话,会把事务管理器中的属性设置为null* ,然后将事务管理器中的属性暂时存储到suspendedResourceHolder中*/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) {/*** 如果在开启新的事务的时候,异常了,就会在下面这个方法中,将事务恢复(和上面挂起是相对的)* ,其实就是把suspendResourceHolder中的属性重新赋值到TransactionSynchronizationManager*/resumeAfterBeginException(transaction, suspendedResources, beginEx);throw beginEx;}
}

由于这个方法中,代码比较多,我就删减了一部分,只留下了propagation_requires_new这个传播机制的代码
可以看到,会先调用suspend(transaction)将当前事务挂起,然后再下面的doBegin()再开启一个新的事务,然后通过prepareSynchronization(),将事务相关信息放入到threadLocal中

suspend(transaction)

/**
* 这是挂起事务的源码* 所谓的事务挂起:就是将当前事务管理器中的相关属性,保存到suspendedResourceHolder中*/
@Nullable
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {/*** 1.如果当前事务是active状态,就将事务挂起,挂起的操作其实也简单* 将当前事务的属性信息暂存到SuspendedResourcesHolder中,然后将当前事务的属性设置为null*/if (TransactionSynchronizationManager.isSynchronizationActive()) {List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();try {Object suspendedResources = null;if (transaction != null) {suspendedResources = doSuspend(transaction);}/*** 1.1 下面就是挂起事务的操作,将事务同步管理器中的属性置为null* , 然后将配置信息,存储到suspendedResources中,以便在恢复事务的时候,可以恢复*/String name = TransactionSynchronizationManager.getCurrentTransactionName();TransactionSynchronizationManager.setCurrentTransactionName(null);boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();TransactionSynchronizationManager.setActualTransactionActive(false);return new SuspendedResourcesHolder(suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);}catch (RuntimeException | Error ex) {/*** 2.如果挂起事务失败,就需要进行回滚,就是将suspendedResourcesHolder* 中的属性重新赋值到TransactionSynchronizationManager中*/// doSuspend failed - original transaction is still active...doResumeSynchronization(suspendedSynchronizations);throw ex;}}else if (transaction != null) {// Transaction active but no synchronization active.Object suspendedResources = doSuspend(transaction);return new SuspendedResourcesHolder(suspendedResources);}else {// Neither transaction nor synchronization active.return null;}
}

这是suspend的源码,可以看到,在1.1这个注释位置,会获取到当前事务的属性信息,然后在下面,会new SuspendedResourcesHolder(),将当前事务属性信息放入到这里面
再下面,就是一些异常的判断和处理,我们可以认为,这个方法就是把事务的属性信息存入到了SuspendedResourcesHolder对象中

newTransactionStatus()

这个方法也很重要,会把刚才创建的suspend对象,放入到DefaultTransactionStatus类中,这里我猜是为了在后面事务恢复的时候用的

doBegin()

在doBegin()方法中,主要是重新获取一个数据库连接,然后设置连接的相关信息,比如:非自动提交等
然后将连接信息存入到TransactionSynchronizationManager对象中
我们可以简单认为doBegin()就是重新开启了一个事务连接

事务恢复

前面讲的是事务挂起,下面来说事务恢复,事务恢复,就是在事务提交或者回滚的时候,会进行事务恢复的处理

这里直接贴了一张图,是事务提交和事务回滚的处理流程,最终都会调用到cleanupAfterCompletion()方法,这个方法就是事务恢复的代码

private void cleanupAfterCompletion(DefaultTransactionStatus status) {status.setCompleted();if (status.isNewSynchronization()) {TransactionSynchronizationManager.clear();}if (status.isNewTransaction()) {doCleanupAfterCompletion(status.getTransaction());}if (status.getSuspendedResources() != null) {if (status.isDebug()) {logger.debug("Resuming suspended transaction after completion of inner transaction");}Object transaction = (status.hasTransaction() ? status.getTransaction() : null);resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());}}

在这个代码中,前面是一些逻辑处理,应该是对当前事务进行清除的操作,需要关注的是最后一行代码,resume()方法

protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)throws TransactionException {if (resourcesHolder != null) {Object suspendedResources = resourcesHolder.suspendedResources;if (suspendedResources != null) {doResume(transaction, suspendedResources);}List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;if (suspendedSynchronizations != null) {TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);doResumeSynchronization(suspendedSynchronizations);}}}

这里可以看到,是从resourcesHolder中取一些参数赋值到TransactionSynchronizationManager中;SuspendedResourcesHolder是哪个对象呢?就是前面事务挂起的时候,将当前事务参数信息赋值到的一个对象

所以:我们可以认为,事务挂起就是将事务赋值到一个临时对象中,事务恢复就是从临时对象中,将事务属性信息赋值到当前事务中

spring事务之事务挂起和事务恢复源码相关推荐

  1. 简单开源java ssm_[VIP源码]【S006】SSM(Spring+Spring MVC+Mybatis) java开源博客管理系统项目源码...

    java源码项目名称:SSM(Spring+Spring MVC+Mybatis) java开源博客管理系统项目源码  java项目源码 1 ?, R, _* q  n8 v) S$ R7 ?百度网盘 ...

  2. Spring学习总结(29)——Spring异步处理@Async的使用以及原理、源码分析(@EnableAsync)

    在开发过程中,我们会遇到很多使用线程池的业务场景,例如异步短信通知.异步记录操作日志.大多数使用线程池的场景,就是会将一些可以进行异步操作的业务放在线程池中去完成.例如在生成订单的时候给用户发送短信, ...

  3. 基于spring boot 的学生科研项目共享平台毕业设计源码271611

    springboot学生科研项目共享平台 摘 要 随着互联网趋势的到来,各行各业都在考虑利用互联网将自己推广出去,最好方式就是建立自己的互联网系统,并对其进行维护和管理.在现实运用中,应用软件的工作规 ...

  4. spring boot信佳玩具有限公司仓库管理系统毕业设计源码011553

    Springboot信佳玩具有限公司仓库管理系统 摘要 本论文主要论述了如何使用java语言开发一个Springboot信佳玩具有限公司仓库管理系统,本系统将严格按照软件开发流程进行各个阶段的工作,采 ...

  5. spring boot大学生就业质量调查分析系统 毕业设计-附源码161457

    大学生就业质量调查分析系统 摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题 ...

  6. Spring的Autowired自动装配(XML版本+Annotation版本+源码+解析)

    http://moshowgame.iteye.com/blog/1607718 @Autowired自动装配 上面的例子我们用的都是手动装配的,如果DAO-Service一多那就很麻烦了,那么我们需 ...

  7. Spring Data Redis—Pub/Sub(附Web项目源码)

    一.发布和订阅机制 当一个客户端通过 PUBLISH 命令向订阅者发送信息的时候,我们称这个客户端为发布者(publisher). 而当一个客户端使用 SUBSCRIBE 或者 PSUBSCRIBE ...

  8. Spring Security之过滤器链【探案】+源码剖析

    Spring Security之过滤器链[探案] Spring Security常用过滤器介绍 过滤器是一种典型的AOP思想,关于什么是过滤器,就不赘述了,接下来咱们就一起看看Spring Secur ...

  9. Spring Boot整合JWT实现用户认证(附源码)

    点击上方"程序IT圈",选择"置顶公众号" 每天早上8点50分进来看看,就是最大的支持 来源:https://dwz.cn/yv1Do6e3 什么是JWT JW ...

最新文章

  1. FPGA之道(23)VHDL的signal、variable与constant
  2. java基础学习(一)方法
  3. 企业托管云模式 浪潮ERP签约山东医药
  4. DCMTK:DSRTree和DSRTreeNodeCursor类的测试程序
  5. js Date 生成某年某月的天数
  6. 小程序 长按转发_小程序转发分享
  7. Node:中间件——express简单的写日志中间件
  8. Hadoop原理之checkpoint机制
  9. Java是什么?Java到底能干嘛?
  10. 常见网站底部友情链接代码示例
  11. GitHub Actions工作流语法
  12. python控制苹果手机触摸屏失灵怎么办_苹果手机触摸屏失灵的各种解决方法
  13. 酷桌面:IPAD上体验office的炫“酷”移动办公应用
  14. 【阅读笔记】联邦学习实战——联邦个性化推荐案例
  15. 颜色转换公式大全及转换表格(31种)
  16. java jsp 获得网页源代码三种方式
  17. Spyder输入中文后光标消失
  18. 【工具】Latex 入门
  19. Oracle 一种简单粗暴的办法解析XML文件的例子
  20. 量子通信(QKD)与BB84协议

热门文章

  1. PB运行库(PB6.5,PB7,PB8,PB9)
  2. 解析 static auto x = []() { std::ios::sync_with_stdio(false);std::cin.tie(nullptr);return 0;}()
  3. windows win10+1050ti maxQ 安装cuda1.0和tensorflow-gpu==2.0.0
  4. 英语二 - 常用词根五
  5. 自定义线程池拒绝策略
  6. Photoshop CS4 锁定图层
  7. 关于租用香港服务器疑问解答
  8. python 去除文本中的中文、中文符号
  9. [原]jQuery .tmpl(), .template()学习
  10. 终于有人把工业数据采集讲明白了