写在前面

  由于实现事务功能的方式各不相同,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开启事务。 分成了几个过程:

  

  1. 获取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)的更多相关文章

  1. spring transaction源码分析--事务架构

    1. 引言  事务特性 事务是并发控制的单元,是用户定义的一个操作序列.这些操作要么都做,要么都不做,是一个不可分割的工作单位.通过事务将逻辑相关的一组操作绑定在一起,以便服务器 保持数据的完整性.事 ...

  2. spring---transaction(1)---源代码分析(事务的拦截器TransactionInterceptor)

    写在前面: 先了解一下spring的事务.分为分明式事务管理和注解式事务管理,对于前期的事务,spring会通过扫描拦截对于事务的方法进行增强(以后讲解). 若果目标方法存在事务,spring产出的b ...

  3. TestNG源代码分析:依赖管理的实现

    TestNG源代码分析:依赖管理的实现 2018-03-19 1 背景 当case之间有依赖关系,有依赖关系的case,它们的执行顺序是有限制的.TestNG提供了依赖管理功能 2 基础理论 这个执行 ...

  4. SDL2源代码分析3:渲染器(SDL_Renderer)

    ===================================================== SDL源代码分析系列文章列表: SDL2源代码分析1:初始化(SDL_Init()) SDL ...

  5. XBMC源代码分析 7:视频播放器(dvdplayer)-输入流(以libRTMP为例)

    前文分析了XBMC的基本结构: XBMC源代码分析 1:整体结构以及编译方法 XBMC源代码分析 2:Addons(皮肤Skin) XBMC源代码分析 3:核心部分(core)-综述 XBMC源代码分 ...

  6. XBMC源代码分析 6:视频播放器(dvdplayer)-文件头(以ffmpeg为例)

    XBMC分析系列文章: XBMC源代码分析 1:整体结构以及编译方法 XBMC源代码分析 2:Addons(皮肤Skin) XBMC源代码分析 3:核心部分(core)-综述 XBMC源代码分析 4: ...

  7. spring---transaction(4)---源代码分析(事务的状态TransactionStatus)

    写在前面 TransactionStatus表示一个具体的事务状态(这里应用到了Java的一个多继承,接口允许多继承) TransactionStatus它继承了SavepointManager接口, ...

  8. redis 源代码分析(一) 内存管理

    一,redis内存管理介绍 redis是一个基于内存的key-value的数据库,其内存管理是很重要的,为了屏蔽不同平台之间的差异,以及统计内存占用量等,redis对内存分配函数进行了一层封装,程序中 ...

  9. spring---transaction(2)---源代码分析(事务的定义TransactionDefinition)

    写在前面 事务属性通过TransactionDefinition接口实现定义,主要有事务隔离级别.事务传播行为.事务超时时间.事务是否只读. public interface TransactionD ...

随机推荐

  1. Docker Compose practice

    Docker Compose 什么是 Docker-Compose? Compose 可以让用户在集群中部署分布式应用.简单的说,Docker Compose 属于一个"应用层"的 ...

  2. 两个Bounding Box的IOU计算代码

    Bounding Box的数据结构为(xmin,ymin,xmax,ymax) 输入:box1,box2 输出:IOU值 import numpy as np def iou(box1,box2): ...

  3. thinkphp模型实例化

    方法一 方法二

  4. jersey HTTP Status 400 - Bad Request

    原因是jersey 内置的转换器,只能做简单的类型转换如: 首先客户端提交上来的一定是String; String ----> String/Long/Boolean 这些基本的 可以转换,但是 ...

  5. 汇编看C函数调用

    http://blog.csdn.net/wishfly/article/details/5022008   简单的函数调用,通过简单的函数调用反汇编可以清楚了解如下 1.栈到底是什么,如何操纵栈的? ...

  6. web文件<async-supported>错误分析

    <async-supported>true</async-supported> 出现 cvc-complex-type.2.4.a: Invalid content was f ...

  7. Oracle学习笔记:parallel并行处理

    在使用oracel查询时,可以通过并行提高查询速度.例如: ) from table_name a; 强行启用并行度来执行当前SQL.加上这个说明之后,可以强行启用Oracle的多线程处理功能,提高效 ...

  8. MySQL学习笔记:计算机服务中找不到MySQL服务

    不知道什么原因,连接了远程服务器之后,本地服务就连接不上. 经排查,发现服务中的MySQL服务居然不见,一番搜索之后,在CMD中进入到MySQL安装目录的bin下执行以下语句: mysqld.exe ...

  9. linux的IPC进程通信方式-匿名管道(一)

    linux的IPC进程通信-匿名管道 什么是管道 如果你使用过Linux的命令,那么对于管道这个名词你一定不会感觉到陌生,因为我们通常通过符号"|"来使用管道,但是管道的真正定义是 ...

  10. 【转载】Node.js 教程(菜鸟教程系列)

    很好的一篇教程:Node.js 教程 简单做下笔记 概述 简单的说 Node.js 就是运行在服务端的 JavaScript. Node.js 是一个基于Chrome JavaScript 运行时建立 ...