@Transactional TransactionManager 源码分析「建议收藏」

@Transactional TransactionManager 源码分析「建议收藏」先贴一篇好文章,https://www.cnblogs.com/thisiswhy/p/13948055.html部分代码得修改下rollback方法必须传入参数transactionStatus,如果用SelfTransactionMananger单实例中的属性transactionStatus,在多线程中会出现线程不安全的情况。ArrayList线程不安全,elementData[size++]=e是先赋值再size+1,多线程运行到赋值还没+1时,size位置上被覆盖了多次…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

先贴一篇好文章,https://www.cnblogs.com/thisiswhy/p/13948055.html

部分代码得修改下   rollback方法必须传入参数 transactionStatus ,如果用SelfTransactionMananger单实例中的属性transactionStatus,在多线程中会出现线程不安全的情况。

@Transactional TransactionManager 源码分析「建议收藏」

ArrayList 线程不安全,elementData[size++] = e是先赋值再size+1,多线程运行到赋值还没+1时,size位置上被覆盖了多次,然后多次+1,size+1,+2等位置没赋值过,下次就直接从size+n开始赋值,看起来就add了null值一样,此时不会报错,因为add时没有null所以取出时没做考虑就可能报NullPointerException了

@Transactional TransactionManager 源码分析「建议收藏」

工作上有一个需求跟文章里的很像,要求任何一个线程发生错误后,所有主线程和子线程里的数据库操作全部回滚。文章中很聪明的用到了”二次确认”的思想,利用CountDownLatch确保所有线程都执行成功后,统一执行commit,如果有一个失败,则全部rollback。

那么数据库事务是如何触发执行commit和rollback的呢?

事务是线程独立的么?

数据库连接池是什么时候借给程序又是怎么回收的呢?

带着这些疑问我们去研读下代码。

话不多说,直接先上流程图,大家先看看,能看懂多少是多少,这里我们先讲解些基本概念,后面会详细梳理流程。

@Transactional TransactionManager 源码分析「建议收藏」

基本概念

DataSourceConfiguration   创建DataSource

@Transactional TransactionManager 源码分析「建议收藏」

DataSourceTransactionManagerAutoConfiguration    创建TransactionManager manager = new DataSourceTransactionManager(dataSource);

@Transactional TransactionManager 源码分析「建议收藏」
TransactionManager    核心方法是   getTransaction,commit, rollback    都由AbstractPlatformTransactionManager的抽象类实现

@Transactional TransactionManager 源码分析「建议收藏」

TransactionInfo    包含属性TransactionManager   TransactionAttribute   TransactionStatus

protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,@Nullable TransactionAttribute txAttr, final String joinpointIdentification) 

Jetbrains全家桶1年46,售后保障稳定

@Transactional TransactionManager 源码分析「建议收藏」

TransactionDefinition    TransactionAttribute        主要属性 isolationLevel   propagationBehavior

TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;

@Transactional TransactionManager 源码分析「建议收藏」

TransactionStaus   主要属性newTransaction   localRollbackOnly   globalRollbackOnly    transaction(一般为DataSourceTransactionObject,可获取connectionHolder  -> 获取connection)

TransactionStatus getTransaction(@Nullable TransactionDefinition definition)  throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;

@Transactional TransactionManager 源码分析「建议收藏」

TransactionInterceptor

@Transactional   spring会将该方法生成cglib代理MethodInvocation,由TransactionInterceptor(MethodInterceptor)执行interceptor.invoke(methodInvocation)   从而实现方法增强

@Transactional TransactionManager 源码分析「建议收藏」

流程梳理

理解了些基础概念后,我们将参照之前的流程图跟着代码走一遍

TransactionAspectSupport.invokeWithinTransaction

核心中的核心,就是这个方法实现了对代理cglib方法的增强

createTransactionIfNecessary    创建txInfo

invocation.proceedWithInvocation   执行interceptor链路,最终执行代理方法

completeTransactionAfterThrowing   如果有异常且该异常满足回滚条件,则执行回滚操作

commitTransactionAfterReturning   如果没异常,但是rollbackOnly=true,也回滚;反之,则执行提交操作

    @Nullable
	protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {
        //...
        //创建transaction   实际调用 transaction.getTransaction(definition)
			TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

			Object retVal;
			try {
				// This is an around advice: Invoke the next interceptor in the chain.
				// This will normally result in a target object being invoked.
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				// 执行rollback
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
				cleanupTransactionInfo(txInfo);
			}

			if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
				// Set rollback-only in case of Vavr failure matching our rollback rules...
				TransactionStatus status = txInfo.getTransactionStatus();
				if (status != null && txAttr != null) {
					retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
				}
			}
            // 执行commit
			commitTransactionAfterReturning(txInfo);
			return retVal;
        //...
}

创建txInfo

@Transactional TransactionManager 源码分析「建议收藏」

TransactionInfo txInfo = createTransactionIfNecessary()    创建transaction,实际调用transactionManager.getTransaction(definition);definition 是TransactionDefinition 类,默认事务级别为 PROPAGATION_REQUIRED

再经过DataTransactionalManager的一系列骚操作

@Transactional TransactionManager 源码分析「建议收藏」

dataSource.getConnection()    由具体的dataSource实现类获得,思路都是由连接池里拿一个未使用的连接出来

@Transactional TransactionManager 源码分析「建议收藏」

核心代码来了,TransactionSynchronizationManager.bindResource 将connectionHolder绑定到ThreadLocal,这样就将connection,TransactionStatus和当前线程绑定了起来

@Transactional TransactionManager 源码分析「建议收藏」

@Transactional TransactionManager 源码分析「建议收藏」

执行代理方法

@Transactional TransactionManager 源码分析「建议收藏」

执行后处理

根据执行结果判断是执行rollback还是commit

@Transactional TransactionManager 源码分析「建议收藏」

TransactionAspectSupport.completeTransactionAfterThrowing  如果抛了异常,则判断是否满足回滚条件

@Transactional TransactionManager 源码分析「建议收藏」

AbstractPlatformTransactionManager     执行回滚操作

@Transactional TransactionManager 源码分析「建议收藏」

TransactionAspectSupport.commitTransactionAfterReturning    没异常则执行commit

@Transactional TransactionManager 源码分析「建议收藏」

AbstractPlatformTransactionManager   执行提交操作   但还需要判断是否标记了rollbackOnly,有可能A,B两个方法共用同一个事务,B抛了异常,导致外层的方法A哪怕没错也得一起回滚。

@Transactional TransactionManager 源码分析「建议收藏」

至此,整个链路就分析完成了

 

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/226796.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 超分辨率——基于SRGAN的图像超分辨率重建(Pytorch实现)[通俗易懂]

    超分辨率——基于SRGAN的图像超分辨率重建(Pytorch实现)[通俗易懂]基于SRGAN的图像超分辨率重建本文偏新手项,因此只是作为定性学习使用,因此不涉及最后的定量评估环节1简要介绍SRGAN的原论文发表于CVPR2017,即《Photo-RealisticSingleImageSuper-ResolutionUsingaGenerativeAdversarialNetwork》SRGAN使用了生成对抗的方式来进行图像的超分辨率重建,同时提出了一个由AdversarialLoss和ContentLoss组成的损失函数。更详细的介绍可以去看看

    2025年7月30日
    4
  • win8最流畅的设置方法_Windows 12

    win8最流畅的设置方法_Windows 12indowsXP终极优化设置(精心整理篇)◆一、系统优化设置◆1、系统常规优化1)关闭系统属性中的特效,这可是简单有效的提速良方。点击开始→控制面板→系统→高级→性能→设置→在视觉效果中,设置为调整为最佳性能→确定即可。2)“我的电脑”-“属性”-“高级”-“错误报告”-选择“禁用错误汇报”。3)再点“启动和故障恢复”-“设置”,将“将事件写入系统日志”、“发送管理警报”、“自动重新启动”这三项

    2022年10月21日
    3
  • 工作站与主域间的信任关系失败_变色龙工作站无法卸载

    工作站与主域间的信任关系失败_变色龙工作站无法卸载症状:登陆域用户,出现错误“此工作站和主域间的信任关系失败”,并无法登陆解决方案:1、使用本地用户登录,更改当前“域”为“工作组”(如默认的WORKGROUP等),并输入具有域管理权限的用户名、密码,随后此电脑上的“域”将会被删除;2、重启电脑3、重新使用域用户信息登陆域4、重启电脑5、登陆成功 或者使用域管理员身份登陆DC服务器,从域中删除此计算机应该也可以。…

    2022年10月10日
    2
  • 使用cookie登录百度网盘(网站使用cookie)

    cookies2.txt为存放cookie字符串的文件。cookie字符串获取方式1.可以通过手动的方式去取,比如登录之后在console里面执行document.cookie即可获得2.在application里面查看cookie的值3.通过webdriver.Chrome(…)创建出来的实例,调用get_cookies()就可以获取到…

    2022年4月10日
    523
  • python自然语言处理情感分析_人工智能拥有感情

    python自然语言处理情感分析_人工智能拥有感情从本专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前一篇文章分享了CNN实现中文文本分类的过程,并与贝叶斯、决策树、逻辑回归、随机森林、KNN、SVM等分类算法进行对比。这篇文章将详细讲解通过自定义情感词典(大连理工词典)实现情感分析和情绪分类的过程,并与SnowNLP进行对比,为后续深度学习和自然语言处理(情感分析、实体识别、实体对齐、知识图谱构建、文本挖掘)结合做基础,希望对您有所帮助~

    2022年8月23日
    12
  • 【技术分享】pip切换镜像源及pip常用命令

    【技术分享】pip切换镜像源及pip常用命令pip切换镜像源国内比较出色的镜像源清华:https://pypi.tuna.tsinghua.edu.cn/simple阿里云:http://mirrors.aliyun.com/pypi/simple中国科技大学https://pypi.mirrors.ustc.edu.cn/simple方法一:切换镜像源#全局设置镜像源地址pipconfigsetglobal.index-urlhttps://pypi.tuna.tsinghua.edu.cn/simple方法二:从指定

    2022年5月11日
    42

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号