Spring3.1.0实现原理分析(二十二).Dao事务分析之事务管理器DataSourceTransactionManager

       大家好,开篇先来谈谈spring事务的优点吧,即spring事务的存在价值。首先它提供了非侵入式编码的事务实现,这个是通过aop实现的,具体的实现过程之前也写博客分析了。

       另外,spring还提供了一套标准的事务管理工作流程。简单的说,事务管理一共可分为三个步骤,分别是初始化事务、提交事务、回滚事务,然后每个步骤又可细分为若干小步骤。spring事务工作流相当于为用户屏蔽了具体orm框架的底层处理逻辑,基于spring开发的程序,即便更换了orm框架,即便从本地事务切换到全局事务,也只需要简单的更改配置,选用合适的事务管理器,基本不会修改代码,这就是spring事务另一个优点。

     Spring3.1.0实现原理分析(二十二).Dao事务分析之事务管理器DataSourceTransactionManager_第1张图片

       Spring的PlatformTransactionManager是事务管理的顶层接口,其中定义的三个方法对应的就是上述的三个步骤,然后AbstractPlatformTransactionManager抽象类给出了三个步骤的具体实现。当然,AbstractPlatformTransactionManager也留下了几个未实现的抽象方法,具体有“创建事务对象”,“开始事务”,“执行提交”,“执行回滚”,这几个抽象方法的实现跟具体的orm框架(如:mybatis,hibernate)或事务特性(如:本地事务,全局事务)有关。比如今天要介绍的主角DataSourceTransactionManager,它实现了上述的抽象方法,它适用的场景是“mybatis”,“ jdbctemplate”,"本地事务"。下面我们就具体分析DataSourceTransactionManager的事务管理三大步骤详细处理流程。


一. DataSourceTransactionManager初始化事务

1. 获取事务名称 

    默认事务名称是被代理类的全限定名称+当前被拦截的方法名称,如: testmybatis.TxDao.findList

2. 获取事务属性对象(TransactionDefinition)

    事务属性对象持有事务的相关配置,比如事务的隔离级别,传播行为,是否只读等。我们开启spring事务管理时,通常都会在配置文件里加入这样一段配置。


	
		
		
	

     spring解析上述配置会创建两个事务属性对象。第一个事务属性对象适用于get前缀的方法对象,它是只读事务;第二个事务对象匹配非get前缀的其它方法,它使用默认事务配置,默认配置的话非只读,事务超时时间为-1,隔离级别使用数据库默认配置,传播行为是PROPAGATION_REQUIRED。

3. 获取事务管理器

    事务管理器跟事务属性对象一样,通常用户都已经配置好了,直接从spring的bean工厂获取,另外从配置也看出DataSourceTransactionManager持有dataSource


    
4. 创建事务对象

    这个方法是AbstractPlatformTransactionManager定义的抽象方法,DataSourceTransactionManager实现了这个抽象方法,它创建的事务对象类型是DataSourceTransactionObject,事务管理器和事务对象之间是存在对应关系的。然后尝试从当前线程获取ConnectionHolder(连接持有器),赋值给事务对象。ConnectionHolder实现了ResourceHolder接口,它持有一个数据库连接,可以把凡是实现了ResourceHolder接口的对象看做是一种资源对象。默认情况下此时当前线程是不存在ConnectionHolder的,因此获取不到插播一句,在spring事务管理过程中会用到一些线程安全对象,这些对象都交由TransactionSynchronizationManager管理,TransactionSynchronizationManager把这些对象都保存在ThreadLocal中

5. 获取被挂起资源持有器

    被挂起资源持有器持有两类被挂起的资源,一类是资源对象,如上述的ConnectionHolder,一类是同步对象,即实现了TransactionSynchronization接口的对象。默认在这个时候事务同步还未被激活,因此返回null。

6. 创建事务状态对象

    被创建的事务状态对象类型是DefaultTransactionStatus,它持有上述创建的事务对象。事务状态对象主要用于获取当前事务对象的状态,比如事务是否被标记了回滚,是否是一个新事务等等。

7. 开始事务 

    7.1. 由于此时事务对象DataSourceTransactionObject持有的ConnectionHolder为null,因此首先需要创建ConnectionHolder对象,创建ConnectionHolder对象的前置条件是要先获取数据库连接对象,于是从dataSource获取连接对象,把连接设置成手动提交,完成ConnectionHolder对象的创建,然后赋值给事务对象。另外这个时候上述的事务属性对象派上用处了,根据事务属性对象配置连接的相关属性,如隔离级别、超时时间等。

    7.2. 把资源对象ConnectionHolder置入线程安全的map,key是dataSource对象,value是ConnectionHolder对象本身,当orm框架执行数据库操作需要连接对象时,获得就是这个ConnectionHolder持有的连接

8. 预准备事务同步(主要是调用TransactionSynchronizationManager对象的方法,设置事务相关同步对象)

    8.1. 设置当前线程事务激活为true。

    8.2. 把事务隔离级别设置到当前线程。

    8.3. 把事务是否只读设置到当前线程。

    8.4. 把事务名称设置到当前线程。

    8.5. 实例化当前线程的同步对象,默认是一个空集。

9. 创建事务信息对象(TransactionInfo)

    事务信息对象持有“事务管理器”,“事务属性对象”,“事务状态对象”,可以把事务信息对象看做对以上几个对象的打包。然后把事务信息对象置入当前线程。

    Spring3.1.0实现原理分析(二十二).Dao事务分析之事务管理器DataSourceTransactionManager_第2张图片

 

二. ORM框架(mybatis)执行数据库操作

1. 通过mybatis's DefaultSessionFactory获取defaultSqlSession。

2. 根据defaultSqlSession创建SqlSessionHolder(资源对象),把SqlSessionHolder置入当前线程,key是DefaultSessionFactory。

3. 创建SqlSessionSynchronization(同步对象),它持有的资源对象是SqlSessionHolder,把同步对象注册到当前线程

4. 从当前线程获取ConnectionHolder对象,key是dataSource,从ConnectionHolder获取连接对象,

5. 执行数据库操作。

关于同步对象,资源对象和事务之间的关系请看下图:

Spring3.1.0实现原理分析(二十二).Dao事务分析之事务管理器DataSourceTransactionManager_第3张图片


三. DataSourceTransactionManager回滚事务

1. 判断是否有必要对抛出的异常执行回滚操作,默认只要异常对象派生自RuntimeException或Error,都会执行回滚操作。这个用户是可以配置的,比如这样。


	
2. 调用事务管理器的rollback(transactionStatus)方法,传入事务状态对象。

    2.1. 触发同步对象的beforeCompletion方法。

    2.2. 从事务对象获取连接持有器,然后再获取连接对象,调用连接的rollback()方法。

    2.3. 触发同步对象的afterCompletion方法。


四. DataSourceTransactionManager提交事务

1. 调用事务管理器的rollback(transactionStatus)方法,传入事务状态对象。

    1.1. 触发同步对象的beforeCommit方法。

    1.2. 触发同步对象的beforeCompletion方法。

    1.3. 从事务对象获取连接持有器,然后再获取连接对象,调用连接的commit()方法。

    1.4. 触发同步对象的afterCommit方法。

    1.5. 触发同步对象的afterCompletion方法。ro


你可能感兴趣的:(Spring3.1.0实现原理分析(二十二).Dao事务分析之事务管理器DataSourceTransactionManager)