spring事务管理器的源码和理解
原文出处: xieyu_zy
以前说了大多的原理,今天来说下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的对象:
|
1
2
3
4
5
|
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="dataSource" /> </property></bean> |
ok,先记录下来,至于下面的NameMatchTransactionAttributeSource描述了那些情况要进行事务管理,我们将它理解为一种属性配置,在运行时需要解析即可,所以他也并不是我们特别需要的重点。
接下里看看:TransactionInterceptor,它看起来有点像拦截器了,他将transactionManager包装进去了;
|
1
2
3
4
5
6
7
8
|
<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了,因为需要自定义的很多状态信息);他执行了一个
|
1
|
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内部都会调用
|
1
|
TransactionSynchronizationManager.getResource(datasouce) |
来获取当前线程的connection。
当然各种连接操作对象也会有自己的transaction操作,他们也会去做setAutoCommit等相应的操作。不过最外层设置后,getConnection方法保证后,内部的操作几乎就可以跳过了。
from: http://www.importnew.com/19455.html
spring事务管理器的源码和理解的更多相关文章
- 【面试】足够“忽悠”面试官的『Spring事务管理器』源码阅读梳理(建议珍藏)
PS:文章内容涉及源码,请耐心阅读. 理论实践,相辅相成 伟大领袖毛主席告诉我们实践出真知.这是无比正确的.但是也会很辛苦. 就像淘金一样,从大量沙子中淘出金子一定是一个无比艰辛的过程.但如果真能淘出 ...
- spring事务管理实现原理-源码-传播属性
转载请标识 https://me.csdn.net/wanghaitao4j https://blog.csdn.net/wanghaitao4j/article/details/83625260 本 ...
- spring事务管理器设计思想(2)
spring事务管理器设计思想(二) 上文见<spring事务管理器设计思想(一)> 对于第二个问题,涉及到事务的传播级别,定义如下: PROPAGATION_REQUIRED-- 如果当 ...
- spring事务管理器设计思想(二)
上文见<spring事务管理器设计思想(一)> 对于第二个问题,涉及到事务的传播级别,定义如下: PROPAGATION_REQUIRED-- 如果当前没有事务,就新建一个事务.这是最常见 ...
- spring事务管理器设计思想(一)
在最近做的一个项目里面,涉及到多数据源的操作,比较特殊的是,这多个数据库的表结构完全相同,由于我们使用的ibatis框架作为持久化层,为了防止每一个数据源都配置一套规则,所以重新实现了数据源,根据线程 ...
- Spring事务管理器的应对
Spring抽象的DAO体系兼容多种数据访问技术,它们各有特色,各有千秋.像Hibernate是非常优秀的ORM实现方案,但对底层SQL的控制不太方便:而iBatis则通过模板化技术让你方便地控制SQ ...
- Spring事务管理器分类
Spring并不直接管理事务,事实上,它是提供事务的多方选择.你能委托事务的职责给一个特定的平台实现,比如用JTA或者是别的持久机制.Spring的事务管理器可以用下表表示: 事务管理器的实例 目标 ...
- Spring事务管理器
1.创建实体和接口 public class Bank { private Integer id; private String name; private String manay; public ...
- Android的Context Manager(服务管理器)源码剖析-android学习之旅(99)
Context Manager介绍 Context Manager对应的进程是servicemanager进程,它先于Service Server和服务客户端运行,进入接收IPC数据的待机状态,处理来 ...
随机推荐
- URLconf+MTV:Django眼中的MVC
MVC是众所周知的模式,即:将应用程序分解成三个组成部分:model(模型),view(视图),和 controller(控制 器).其中: M 管理应用程序的状态(通常存储 ...
- Bootstrap进阶二:基本组件
基本组件是Bootstrap的精华之一,其中都是开发者平时需要用到的交互组件.例如:网站导航.标签页.工具条.面包屑.分页栏.提示标签.产品展示.提示信息块和进度条等.这些组件都配有jQuery插件, ...
- Oracle数据库脚本中的set define off
2018年8月6日15:11:34 Oracle数据库脚本中的set define off 前言 最近在公司写需求,接触到脚本,第一句set define off;就不知道什么意思了,查询后记录之. ...
- 基于特征码文件恢复工具magicrescue
基于特征码文件恢复工具magicrescue 常见类型的文件都包含一些特殊的字节,用来标识文件的类型.这些字节被称为特征码.在磁盘中,当记录文件存储位置的簇损坏后,就可以基于这些特征码来恢复文件. ...
- 配置k8s dns
DNS (domain name system),提供域名解析服务,解决了难于记忆的IP地址问题,以更人性可读可记忆可标识的方式映射对应IP地址. Cluster DNS扩展插件用于支持k8s集群系统 ...
- MySql 模糊查询、范围查询
实例: SQL模糊查询,使用like比较关键字,加上SQL里的通配符,请参考以下: 1.LIKE'Mc%' 将搜索以字母 Mc 开头的所有字符串(如 McBadden). 2.LIKE'%inger' ...
- 【BZOJ 2721】 2721: [Violet 5]樱花 (筛)
2721: [Violet 5]樱花 Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 599 Solved: 354 Description Input ...
- luoguP4503 [CTSC2014]企鹅QQ hash
既然只有一位的不同,那么我们可以枚举这一位.... 我们只需要快速地计算去掉某一位的$hash$值.... 由于$hash(S) = \sum s[i] * seed^i$,因此去掉第$i$位的权值只 ...
- 转 MySQL连接超时
在负载较重的MySQL服务器上,有时你偶尔会看到一些连接超时的错误,诸如: Can’t connect to MySQL server on ‘mydb’(110).如果当时你有多个连接请求,你会发现 ...
- 【ACM-ICPC 2018 徐州赛区网络预赛】E. End Fantasy VIX 血辣 (矩阵运算的推广)
Morgana is playing a game called End Fantasy VIX. In this game, characters have nn skills, every ski ...