spring事务管理器的源码和理解

以前说了大多的原理,今天来说下spring的事务管理器的实现过程,顺带源码干货带上。

其实这个文章唯一的就是带着看看代码,但是前提你要懂得动态代理以及字节码增强方面的知识(http://blog.csdn.net/xieyuooo/article/details/7624146),关于annotation在文章:http://blog.csdn.net/xieyuooo/article/details/8002321

也有说明,所以本文也就带着看看代码而已。

关于annotation这里就不说了,我们看看平时一般会怎么样来配置spring的配置,通过配置文件反射源码如何看看。

一般来讲首先会配置一个datasource,至于你配置什么连接池还是用JNDI这里就不提到细节,总之我们认为配置的spring的全局名称为dataSource就可以了。

接下来会将datasource交给各种连接池的操作类,如:ibatis、jdbcTemplate等等,这些不是我们关心的重点,我们需要关心的是dataSource是谁来管理了,在spring中配置了给一个DataSourceTransactionManager的对象:

 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource">
     <ref bean="dataSource" />
    </property>
</bean>

ok,先记录下来,至于下面的NameMatchTransactionAttributeSource描述了那些情况要进行事务管理,我们将它理解为一种属性配置,在运行时需要解析即可,所以他也并不是我们特别需要的重点。

接下里看看:TransactionInterceptor,它看起来有点像拦截器了,他将transactionManager包装进去了;

<bean id="txInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
  <property name="transactionManager">
    <ref bean="transactionManager"/>
  </property>
  <property name="transactionAttributeSource">
    <ref bean="txAttributes"/>
  </property>
</bean>

这里是一个点,再继续看,BeanNameAutoProxyCreator,这个看名字就知道是自动代理的类了,并且包装了TransactionInterceptor的对象进去,也就是这个地方就是代理,然后会将事务的处理交给TransactionInterceptor拦截器来完成,可能这个不是我们的重点,不过简单看看也无妨,这个类细节代码就不贴了,进去你会看到就是讲拦截器包装后,然后通过beanName设置哪些类需要被拦截,根据你的配置来完成,spring 后来基于annotation实现的就不是这样,他会扫描类中的annotation来实现类似的功能。

一起来简单看看TransactionInterceptor吧:

细节代码太多,看关键代码,红色部分表示出来了,其实在AOP调用中,我们比较关注invoke、intercept这类代码关联字的方法,因为proxy调用的就是他们,由他们自己去调用其他的方法,这里invoke首先发现在事务下,首先调用了createTranscationIfNecessary这个方法。

跟踪进去看看:

这里看到开始获取TransactionManager了,get方法没啥好看的,配置文件注入进去了,我们看看tm.getTranscation里头做了啥。

也就是跟踪到你set的那个TranscationManager里头去了,PlatformTransactionManager有多个实现类,注意选择自己实现的那部分:本程序中叫:DataSourceTransactionManager,跟踪进去看看getTransaction方法

这个代理类,需要注意几个加红色的地方:

1、目前看来应该是获事务的方法

2、部分如果发现事务对象获取到就直接返回

3、做一个doBegin的操作,这i类关键字一般是指切入时的预先操作,那么闲看看这个doBegin干啥了

我们想要的东西来了,相信看到第二个红色区域部分,大家都会很熟悉自己做事务是怎么做的,发现spring也是这样做的。

将connection做了一个setAutoCommit(false);非自动提交模式,接下来就要看如何和框架结合起来了,如何让调用的时候使用到这个connection,调用方如何知道使用这个connection;

看另外两个红色的部分:

第一个红色部分可以看出是获取事务对象若为空(不是事务或已经是事务),则从datasource对象中获取一个connection,包装成一个handle,放入事务对象中(事务对象内部的包装请自己去看下)。

而第三个额部分是,如果是一个新的ConnectionHandler(其实判定的是一些状态,使用中,spring会修改handler的状态,这也是为什么spring要包装一个handler了,因为需要自定义的很多状态信息);他执行了一个

TransactionSynchronizationManager.bindResource(getDatasource() , txObject.getConnectionHolder());

这样一个操作,可见:TransactionSynchronizationManager提供了一个静态方法getDatasource(),看名称是绑定的意思,那么绑定什么呢?我们跟踪进去看看:

咦,resouces貌似里面有一个map,如果为空,就put一个进去,那么resouce是个什么东西呢?他会不会有线程冲突的问题?

看看resouces是什么:

ThreadLocal,对了,就是它了,有关ThreadLocal的原理和细节,我这不想多提,也不是这里的重点,这里明确的就是,虽然它是全局的一个静态属性,不过他是线程安全的,不论是get还是set还是remove。

我们知道这个connection被绑定到当前运行的线程中了,接下来只需要在使用时从这个里面获取出来即可。

我们再回到上面看到的doTransaction方法还没看细节,这里来看看。

可以看到,它果然是从这里来获取保存到当前线程的connection。

貌似看得差不多了,好像少了一半,那一半,datasouces是各个厂家的,他们的各自的datasouce方法是自己的,getConnection内部有自己的算法,如何做到他们在getConnection的时候,执行相应的,这个时候,我们来看看一个拦截connection的方式:TransactionAwareDataSourceProxy,

他内部有啥道理所在:

这里可以看到使用了动态代理,获取相应的datasouces,那么就找到对应的代理类里面去看看他的invoke方法是什么:

TransactionAwareInvocationHandler里面,可以跟踪这个是一个内部类了,进去看看他的invoke方法:

可以看到切入的位置,向上看到两个红色部分是要去获取connection,我们跟踪进去看看:

接下来的就不用多说了吧,回到刚才的代码,不论是doGetConnection还是doReleaseConnection内部都会调用

TransactionSynchronizationManager.getResource(datasouce)

来获取当前线程的connection。

当然各种连接操作对象也会有自己的transaction操作,他们也会去做setAutoCommit等相应的操作。不过最外层设置后,getConnection方法保证后,内部的操作几乎就可以跳过了。

时间: 2025-01-30 01:50:15

spring事务管理器的源码和理解的相关文章

分布式事务系列(1.1)Spring事务管理器PlatformTransactionManager

1 系列目录 分布式事务系列(开篇)提出疑问和研究过程 分布式事务系列(1.1)Spring事务管理器PlatformTransactionManager源码分析 分布式事务系列(1.2)Spring事务体系 分布式事务系列(2.1)分布式事务模型与接口定义 分布式事务系列(3.1)jotm的分布式案例 分布式事务系列(3.2)jotm分布式事务源码分析 分布式事务系列(4.1)Atomikos的分布式案例 2 jdbc事务 2.1 例子 public void save(User user)

Spring事务管理高级应用难点剖析,第1部分

概述 Spring 最成功,最吸引人的地方莫过于轻量级的声明式事务管理,仅此一点,它就宣告了 重量级 EJB 容器的覆灭.Spring 声明式事务管理将开发者从繁复的事务管理代码中解脱出来 ,专注于业务逻辑的开发上,这是一件可以被拿来顶礼膜拜的事情.但是,世界并未从此消停 ,开发人员需要面对的是层出不穷的应用场景,这些场景往往逾越了普通 Spring 技术书籍的 理想界定.因此,随着应用开发的深入,在使用经过 Spring 层层封装的声明式事务时,开发 人员越来越觉得自己坠入了迷雾,陷入了沼泽,

Spring事务管理--多个ORM框架在使用时的情况分析

   公司的项目已经接近尾声了,总结一下项目中用到的技术,我发现项目中的有些东西还是挺模糊的,只是知道这么用就行了.并不清楚其中的原理.由于公司的项目比较老,是7年前的一个项目了,中间一直有人在维护,也是在这个过程中不断融入了新的东西,比如就项目的持久化这块来说,就用了ibatis.mybatis.hibernate.spring JDBC四种混合的框架.究其原因只能说是历史遗留问题,就不做过多的解释了.但是这么多持久化的框架如何协同工作的,尤其是事务的控制,一个系统中使用如此多的持久化框架是,

Spring 事务管理高级应用难点剖析: 第 1 部分

Spring 的事务管理是被使用得最多的功能之一,虽然 Spring 事务管理已经帮助程序员将要做的事情减到了最小.但在实际开发中,如果使用不当,依然会造成数据连接泄漏等问题.本系列以实际应用中所碰到的各种复杂的场 景为着眼点,对这些应用的难点进行深度的剖析. DAO 和事务管理的牵绊 很少有使用 Spring 但不使用 Spring 事务管理器的应用,因此常常有人会问:是否用了 Spring,就一定要用 Spring 事务管理器,否则就无法进行数据的持久化操作呢?事务管理器和 DAO 是什么关

Spring 事务管理高级应用难点剖析: 第 2 部分

本文是"Spring 事务管理高级应用难点剖析" 系列文章的第 2 部分,作者将继续深入剖析在实际 Spring 事务管理应用中容易遇见的一些难点,包括混合使用多种数据访问技术(如 Spring JDBC + Hibernate)的事务管理问题,以及通过 Spring AOP 增强的 Bean 存在的一些比较特殊的情况. 联合军种作战的混乱 Spring 抽象的 DAO 体系兼容多种数据访问技术,它们各有特色,各有千秋.像 Hibernate 是非常优秀的 ORM 实现方案,但对底层

使用KTM(内核事务管理器)进行文件事务处理

在本人最近的几篇关于事务处理的文章中,从事务处理的整体概念到具体的C#代码的实践操作基本上都已经能满足日常的开发需求.文章中大部分的事务范围类的操作都是局限于数据库,在本人的".NET简谈自定义事务资源管理器 "一文中我虽然实现了一个简单的自定义资源管理器,其实也能满足基本的项目需求,核心功能也实现了,但是对于文件事务操作我们是力不从心的.[王清培版权所有,转载请给出署名] 从数据库到自定义资源管理器都能参与到事务处理中来,在必要的时候保证数据的完整性,那么我们缺一个类型的资源操作,当

Spring事务管理高级应用难点剖析: 第2部分

联合军种作战的混乱 Spring 抽象的 DAO 体系兼容多种数据访问技术,它们各有特 色,各有千秋.像 Hibernate 是非常优秀的 ORM 实现方案,但对底层 SQL 的控制不太方便: 而 iBatis 则通过模板化技术让您方便地控制 SQL,但没有 Hibernate 那样高的开发效率:自 由度最高的当然是直接使用 Spring JDBC 莫属了,但是它也是最底层的,灵活的代价是代码的 繁复.很难说哪种数据访问技术是最优秀的,只有在某种特定的场景下,才能给出答案.所以 在一个应用中,往

spring 事务管理让我费解的地方

问题描述 在用springmvc时,用到了spring事务管理<beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close"><propertyname="driverClassName"><value>${jdbc.driver}</value></prop

Spring事务管理—aop:pointcut expression解析

  先来看看这个spring的配置文件的配置:     <!-- 事务管理器 -->  <bean id="transactionManager"   class="org.springframework.orm.hibernate3.HibernateTransactionManager">   <property name="sessionFactory" ref="sessionFactory&quo