spring事务源码分析结合mybatis源码(二)
让我们继续上篇,分析下如果有第二个调用进入的过程。
代码部分主要是下面这个:
if (isExistingTransaction(transaction)) {
return handleExistingTransaction(definition, transaction, debugEnabled);
}
protected boolean isExistingTransaction(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
return (txObject.getConnectionHolder() != null && txObject.getConnectionHolder().isTransactionActive());
}
isExistingTransaction这个方法主要是用来判断当前线程是否已经存在一个transaction,并且是active,如果是的话进入handleExistingTransaction方法:
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException { 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) {
Object suspendedResources = suspend(transaction);
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
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 beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
catch (Error beginErr) {
resumeAfterBeginException(transaction, suspendedResources, beginErr);
throw beginErr;
}
} 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 (useSavepointForNestedTransaction()) {
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
status.createAndHoldSavepoint();
return status;
}
else {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, null);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
}
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");
}
}
}
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}
核心的就是这一块了,让我们对这块来分析下:
首先根据definition.getPropagationBehavior()属性来判断当前事务属性,比如说当definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW时候,也就是新建一个事务,看其中的代码完全跟之前分析第一个事务开启的时候一样。
而如果当definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED时候,将新建一个保存点事务。
否则将执行到最后,也就是当definition.getPropagationBehavior()=TransactionDefinition.PROPAGATION_REQUIRED的时候,将初始化一个TransactionStatus,并且将此TransactionStatus的newTransaction属性置为false。
其后的调用过程跟上篇分析一致,而提交或者回滚的时候都会根据TransactionStatus进行一些判断。
spring事务源码分析结合mybatis源码(二)的更多相关文章
- spring事务源码分析结合mybatis源码(三)
下面将结合mybatis源码来分析下,这种持久化框架是如何对connection使用,来达到spring事务的控制. 想要在把mybatis跟spring整合都需要这样一个jar包:mybatis-s ...
- spring事务源码分析结合mybatis源码(一)
最近想提升,苦逼程序猿,想了想还是拿最熟悉,之前也一直想看但没看的spring源码来看吧,正好最近在弄事务这部分的东西,就看了下,同时写下随笔记录下,以备后查. spring tx源码分析 这里只分析 ...
- spring事务详解(三)源码详解
系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...
- 精尽MyBatis源码分析 - SQL执行过程(二)之 StatementHandler
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- Spring Ioc源码分析系列--Ioc源码入口分析
Spring Ioc源码分析系列--Ioc源码入口分析 本系列文章代码基于Spring Framework 5.2.x 前言 上一篇文章Spring Ioc源码分析系列--Ioc的基础知识准备介绍了I ...
- Spring Ioc源码分析系列--Bean实例化过程(二)
Spring Ioc源码分析系列--Bean实例化过程(二) 前言 上篇文章Spring Ioc源码分析系列--Bean实例化过程(一)简单分析了getBean()方法,还记得分析了什么吗?不记得了才 ...
- 深入源码分析SpringMVC底层原理(二)
原文链接:深入源码分析SpringMVC底层原理(二) 文章目录 深入分析SpringMVC请求处理过程 1. DispatcherServlet处理请求 1.1 寻找Handler 1.2 没有找到 ...
- Solr4.8.0源码分析(19)之缓存机制(二)
Solr4.8.0源码分析(19)之缓存机制(二) 前文<Solr4.8.0源码分析(18)之缓存机制(一)>介绍了Solr缓存的生命周期,重点介绍了Solr缓存的warn过程.本节将更深 ...
- NIO 源码分析(05) Channel 源码分析
目录 一.Channel 类图 二.begin 和 close 是什么 2.1 AbstractInterruptibleChannel 中的 begin 和 close 2.2 Selector 中 ...
随机推荐
- IDEA+快捷键
格式化代码:ctrl+alt+L IDEA快捷键管理:https://blog.csdn.net/h8178/article/details/78328097 (duplicate:为复制上一行)
- .Net Core应用框架Util介绍(三)
上篇介绍了Util的开发环境,并让你把Demo运行起来.本文将介绍该Demo的前端Angular运行机制以及目录结构. 目录结构 在VS上打开Util Demo,会看见如下的目录结构. 现代前端通常采 ...
- webpack4配置详解之常用插件分享
前言 继上一次webpack的基础配置分享之后,本次将分享一些工作中项目常用的配置插件.也会包含一些自己了解过觉得不错的插件,如有分析不到位的,欢迎纠错,嗯,这些东西文档都有,大佬可绕过. Wepac ...
- redis--小白博客
概述 redis是一种nosql数据库,他的数据是保存在内存中,同时redis可以定时把内存数据同步到磁盘,即可以将数据持久化,并且他比memcached支持更多的数据结构(string,list列表 ...
- JMeter配置好环境变量后无法启动---翻车笔记
双击jmeter.bat出现下图情况 手欠了win7中配置 path无意中多删了变量 解决方法:在计算机-属性-高级系统设置-环境变量Path中添加 %SystemRoot%/system32;%Sy ...
- Jmeter Thread Group中如果存在HTTP request执行失败,就对整个Thread Group重新执行,限定最大执行次数N次
由于在对WEB系统进行自动化测试的过程中,经常会由于握手连接断开等原因导致HTTP请求发送失败,如果重新执行一次,会是成功的.在每天的自动化冒烟测试过程中,生成在测试报告存在误报,严重浪费了测试人员确 ...
- [转帖]内置系统账户:Local system/Network service/Local Service 区别
内置系统账户:Local system/Network service/Local Service 区别 学习使用 xp_cmdshell 的时候 发现必须 sqlserver 的服务运行在local ...
- AngularJS 1.x系列:Node.js安装及npm常用命令(1)
1. Node.js安装 1.1 Node.js下载 Node.js官网:https://nodejs.org 当前下载版本(含npm):Latest LTS Version: v6.10.3 (in ...
- EntityFramework优化:第一次启动优化
1. 预先生成视图 通过代码的方式来预先生成视图,要求EntityFramework是6.0及以上版本. 控制台程序: using System.Data.Entity.Infrastructure; ...
- mysql-笔记--增删改查
查看数据库:可以使用 show databases; 命令查看已经创建了哪些数据库 指定数据库:在登录后使用 use 语句指定, 命令: use 数据库名;要对一个数据库进行操作, 必须先选择该数据库 ...