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方法保证后,内部的操作几乎就可以跳过了。


目录
相关文章
|
1月前
|
XML 缓存 Java
Spring源码之 Bean 的循环依赖
循环依赖是 Spring 中经典问题之一,那么到底什么是循环依赖?简单说就是对象之间相互引用, 如下图所示: 代码层面上很好理解,在 bean 创建过程中 class A 和 class B 又经历了怎样的过程呢? 可以看出形成了一个闭环,如果想解决这个问题,那么在属性填充时要保证不二次创建 A对象 的步骤,也就是必须保证从容器中能够直接获取到 B。 一、复现循环依赖问题 Spring 中默认允许循环依赖的存在,但在 Spring Boot 2.6.x 版本开始默认禁用了循环依赖 1. 基于xml复现循环依赖 定义实体 Bean java复制代码public class A {
|
1月前
|
监控 Java 数据处理
【Spring云原生】Spring Batch:海量数据高并发任务处理!数据处理纵享新丝滑!事务管理机制+并行处理+实例应用讲解
【Spring云原生】Spring Batch:海量数据高并发任务处理!数据处理纵享新丝滑!事务管理机制+并行处理+实例应用讲解
|
1月前
|
Java 数据库 Spring
Spring事务失效的场景详解
Spring事务失效的场景详解
29 0
|
1月前
|
Java 数据库 Spring
Spring事务的传播机制(行为、特性)
Spring事务的传播机制(行为、特性)
32 0
|
1月前
|
Java 数据库 Spring
【spring(四)】Spring事务管理和@Transactional注解
【spring(四)】Spring事务管理和@Transactional注解
|
2月前
|
Java 关系型数据库 数据库连接
Spring源码解析--深入Spring事务原理
本文将带领大家领略Spring事务的风采,Spring事务是我们在日常开发中经常会遇到的,也是各种大小面试中的高频题,希望通过本文,能让大家对Spring事务有个深入的了解,无论开发还是面试,都不会让Spring事务成为拦路虎。
35 1
|
1月前
|
Java 测试技术 数据库连接
【Spring源码解读!底层原理高级进阶】【下】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨
【Spring源码解读!底层原理高级进阶】【下】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨
|
1天前
|
Java 关系型数据库 MySQL
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
UWB (ULTRA WIDE BAND, UWB) 技术是一种无线载波通讯技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。一套UWB精确定位系统,最高定位精度可达10cm,具有高精度,高动态,高容量,低功耗的应用。
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
|
5天前
|
安全 前端开发 Java
Spring Security的授权管理器实现
Spring Security的授权管理器涉及用户登录后的token验证和权限检查。当用户携带token访问时,框架会验证token合法性及用户访问权限。自定义授权管理器`TokenAuthorizationManager`需实现`AuthorizationManager&lt;RequestAuthorizationContext&gt;`接口,处理校验逻辑,包括解析token、判断用户角色与访问资源的匹配。配置中在`SecurityConfig`注册该管理器以生效。测试表明,具有不同角色的用户可访问相应权限的资源,否则返回403错误。
116 4
|
30天前
|
Java Spring
使用spring实现邮件的发送(含测试,源码,注释)
使用spring实现邮件的发送(含测试,源码,注释)
7 0