spring---transaction(3)---源代码分析(事务的管理器PlatformTransactionManager)
写在前面
由于实现事务功能的方式各不相同,Spring进行了统一的抽象,形成了PlatformTransactionManager事务管理器顶级接口(平台事务管理器),事务的提交、回滚等操作全部交给它来实现
先来看下三大接口
PlatformTransactionManager : 事务管理器
TransactionDefinition : 事务的一些基础信息,如超时时间、隔离级别、传播属性等
TransactionStatus : 事务的一些状态信息,如是否是一个新的事务、是否已被标记为回滚
一般我们给事务管理器的默认实现为DataSourceTransactionManager
<!-- 事务管理器配置 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
DataSourceTransactionManager(事务管理器接口定义PlatformTransactionManager)
PlatformTransactionManager
- AbstractPlatformTransactionManager
- DataSourceTransactionManager(重点)
- HibernateTransactionManager
- JpaTransactionManager
public interface PlatformTransactionManager {
//获取一个具体的事务状态信息
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
//提交一个事务状态信息
void commit(TransactionStatus status) throws TransactionException;
//回滚一个事务状态信息
void rollback(TransactionStatus status) throws TransactionException;
}
获取Object transaction:
大体内容就是先获取上述说明(TransactionStatus)的Object transaction,判断当前事务是否已存在,如果存在则进行事务的传播属性处理,后面详细说明,如果不存在new DefaultTransactionStatus,新创建一个事务,同时使用Object transaction开启事务。 分成了几个过程:
- 获取Object transaction:不同的事务管理器获取不同的Object transaction
DataSourceTransactionManager就是获取上述的DataSourceTransactionObject
从当前线程中获取绑定的ConnectionHolder,可能为null,如果为null,则会在下一个开启事务的过程中,从dataSource中获取一个Connection,封装成ConnectionHolder,然后再绑定到当前线程
然后我们new 一个DataSourceTransactionObject了,具体过程如下:
@Override
protected Object doGetTransaction() {
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
txObject.setSavepointAllowed(isNestedTransactionAllowed());
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
HibernateTransactionManager获取HibernateTransactionObject
从当前线程中获取绑定的SessionHolder,可能为null,如果为null,则会在下一个开启事务的过程中从sessionFactory中获取一个session,然后封装成SessionHolder,然后再绑定到当前线程
然后我们就可以new 一个HibernateTransactionObject了,具体过程如下:
@Override
protected Object doGetTransaction() {
HibernateTransactionObject txObject = new HibernateTransactionObject();
txObject.setSavepointAllowed(isNestedTransactionAllowed()); SessionHolder sessionHolder =
(SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
if (sessionHolder != null) {
if (logger.isDebugEnabled()) {
logger.debug("Found thread-bound Session [" + sessionHolder.getSession() + "] for Hibernate transaction");
}
txObject.setSessionHolder(sessionHolder);
}
else if (this.hibernateManagedSession) {
try {
Session session = this.sessionFactory.getCurrentSession();
if (logger.isDebugEnabled()) {
logger.debug("Found Hibernate-managed Session [" + session + "] for Spring-managed transaction");
}
txObject.setExistingSession(session);
}
catch (HibernateException ex) {
throw new DataAccessResourceFailureException(
"Could not obtain Hibernate-managed Session for Spring-managed transaction", ex);
}
} if (getDataSource() != null) {
ConnectionHolder conHolder = (ConnectionHolder)
TransactionSynchronizationManager.getResource(getDataSource());
txObject.setConnectionHolder(conHolder);
} return txObject;
}
2. 构建DefaultTransactionStatus,使用Object transaction开启事务
DataSourceTransactionManager的DataSourceTransactionObject开启过程如下:
首先判断之前的获取当前线程绑定的ConnectionHolder是否为null,如果为null,从dataSource中获取一个Connection,封装成ConnectionHolder,然后再绑定到当前线程因为开启了一个事务,则必须要关闭DataSourceTransactionObject中Connection的自动提交
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null; try {
if (txObject.getConnectionHolder() == null ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
Connection newCon = this.dataSource.getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
} txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection(); Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel); // Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
// so we don't want to do it unnecessarily (for example if we've explicitly
// configured the connection pool to set it already).
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
if (logger.isDebugEnabled()) {
logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
}
con.setAutoCommit(false);
}
txObject.getConnectionHolder().setTransactionActive(true); int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
} // Bind the session holder to the thread.
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
}
} catch (Throwable ex) {
if (txObject.isNewConnectionHolder()) {
DataSourceUtils.releaseConnection(con, this.dataSource);
txObject.setConnectionHolder(null, false);
}
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
}
}
HibernateTransactionManager的HibernateTransactionObject开启过程如下:
也是同样的逻辑,如果SessionHolder为null,则从SessionFactory中获取一个Session,然后封装成SessionHolder,然后把这个SessionHolder绑定到当前线程
3. 第二个接口:void rollback(TransactionStatus status) 回滚事务
回滚,则还是利用DefaultTransactionStatus内部的Object transaction来执行回滚操作
DataSourceTransactionManager就是使用DataSourceTransactionObject中的Connection来进行回滚操作
@Override
protected void doRollback(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
}
try {
con.rollback();
}
catch (SQLException ex) {
throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
}
}
HibernateTransactionManager就是使用HibernateTransactionObject中的SessionHolder中的Session创建的事务Transaction来进行回滚操作
@Override
protected void doRollback(DefaultTransactionStatus status) {
HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();
if (status.isDebug()) {
logger.debug("Rolling back Hibernate transaction on Session [" +
txObject.getSessionHolder().getSession() + "]");
}
try {
txObject.getSessionHolder().getTransaction().rollback();
}
catch (org.hibernate.TransactionException ex) {
throw new TransactionSystemException("Could not roll back Hibernate transaction", ex);
}
catch (HibernateException ex) {
// Shouldn't really happen, as a rollback doesn't cause a flush.
throw convertHibernateAccessException(ex);
}
finally {
if (!txObject.isNewSession() && !this.hibernateManagedSession) {
// Clear all pending inserts/updates/deletes in the Session.
// Necessary for pre-bound Sessions, to avoid inconsistent state.
txObject.getSessionHolder().getSession().clear();
}
}
}
4.第三个接口: void commit(TransactionStatus status) 提交事务
同理,DataSourceTransactionManager依托内部的Connection来完成提交操作
HibernateTransactionManager依托内部的Transaction来完成提交操作
spring---transaction(3)---源代码分析(事务的管理器PlatformTransactionManager)的更多相关文章
- spring transaction源码分析--事务架构
1. 引言 事务特性 事务是并发控制的单元,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位.通过事务将逻辑相关的一组操作绑定在一起,以便服务器 保持数据的完整性.事 ...
- spring---transaction(1)---源代码分析(事务的拦截器TransactionInterceptor)
写在前面: 先了解一下spring的事务.分为分明式事务管理和注解式事务管理,对于前期的事务,spring会通过扫描拦截对于事务的方法进行增强(以后讲解). 若果目标方法存在事务,spring产出的b ...
- TestNG源代码分析:依赖管理的实现
TestNG源代码分析:依赖管理的实现 2018-03-19 1 背景 当case之间有依赖关系,有依赖关系的case,它们的执行顺序是有限制的.TestNG提供了依赖管理功能 2 基础理论 这个执行 ...
- SDL2源代码分析3:渲染器(SDL_Renderer)
===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...
- XBMC源代码分析 7:视频播放器(dvdplayer)-输入流(以libRTMP为例)
前文分析了XBMC的基本结构: XBMC源代码分析 1:整体结构以及编译方法 XBMC源代码分析 2:Addons(皮肤Skin) XBMC源代码分析 3:核心部分(core)-综述 XBMC源代码分 ...
- XBMC源代码分析 6:视频播放器(dvdplayer)-文件头(以ffmpeg为例)
XBMC分析系列文章: XBMC源代码分析 1:整体结构以及编译方法 XBMC源代码分析 2:Addons(皮肤Skin) XBMC源代码分析 3:核心部分(core)-综述 XBMC源代码分析 4: ...
- spring---transaction(4)---源代码分析(事务的状态TransactionStatus)
写在前面 TransactionStatus表示一个具体的事务状态(这里应用到了Java的一个多继承,接口允许多继承) TransactionStatus它继承了SavepointManager接口, ...
- redis 源代码分析(一) 内存管理
一,redis内存管理介绍 redis是一个基于内存的key-value的数据库,其内存管理是很重要的,为了屏蔽不同平台之间的差异,以及统计内存占用量等,redis对内存分配函数进行了一层封装,程序中 ...
- spring---transaction(2)---源代码分析(事务的定义TransactionDefinition)
写在前面 事务属性通过TransactionDefinition接口实现定义,主要有事务隔离级别.事务传播行为.事务超时时间.事务是否只读. public interface TransactionD ...
随机推荐
- 转载:Github项目解析(七)-->防止按钮重复点击
不错的东西,记录下... http://46aae4d1e2371e4aa769798941cef698.devproxy.yunshipei.com/qq_23547831/article/deta ...
- 10 The Go Programming Language Specification go语言规范 重点
The Go Programming Language Specification go语言规范 Version of May 9, 2018 Introduction 介绍 Notation 符号 ...
- 基于RESTful API 设计用户权限控制
RESTful简述 本文是基于RESTful描述的,需要你对这个有初步的了解. RESTful是什么? Representational State Transfer,简称REST,是Roy Fiel ...
- CCF CSP 201703-5 引水入城(50分)
CCF计算机职业资格认证考试题解系列文章为meelo原创,请务必以链接形式注明本文地址 CCF CSP 201703-5 引水入城 问题描述 MF城建立在一片高原上.由于城市唯一的水源是位于河谷地带的 ...
- Singleton 多线程
单例模式 何为单例模式,在GOF的<设计模式:可复用面向对象软件的基础>中是这样说的:保证一个类只有一个实例,并提供一个访问它的全局访问点.首先,需要保证一个类只有一个实例:在类中,要构造 ...
- 在Ubuntu 16.04 安装python3.6 环境并设置为默认
在Ubuntu 16.04 安装python3.6 环境并设置为默认 1.添加python3.6安装包,并且安装 sudo apt-get install software-properties-co ...
- bzoj 1233
先要了解一个结论,在多种可行的堆叠方案中,至少有一种能使层数最高的方案同时使得底边最短.即底边最短的,层数一定最高. dp[ i ] = min(sum[j - 1] - sum[i - 1]) j ...
- 如何让 C++ 和 C# 一样易用,而且效率更高?
(未完成,待续..) 第一章:C++基本功 1. 养成良好的编码习惯. 2. 堆上的资源随用随还,严格控制生命周期. 第二章:一些调试心得 1. 在VisualStudio环境下,曾出现 Detect ...
- Ionic Js十五:对话框
$ionicPopup ionic 对话框服务允许程序创建.显示弹出窗口. $ionicPopup 提供了3个方法:alert(), prompt(),以及 confirm() . 实例 HTML 代 ...
- PHP中双引号引起的命令执行漏洞
前言 在PHP语言中,单引号和双引号都可以表示一个字符串,但是对于双引号来说,可能会对引号内的内容进行二次解释,这就可能会出现安全问题. 正文 举个简单例子 <?php $a = 1; $b = ...