61 张图,剖析 Spring 事务,就是要钻到底!

网站建设4年前发布
98 0 0

大家好,我是楼仔!,下面我会简单介绍一下 Spring 事务的基础知识,以及使用方法,然后直接对源码进行拆解。,不 BB,上文章目录。,61 张图,剖析 Spring 事务,就是要钻到底!,需要搭建环境的同学,代码详见:https://github.com/lml200701158/program_demo/tree/main/spring-transaction,下面是 DB 数据和 DB 操作接口:,基础测试代码,testSuccess() 是事务生效的情况:,执行入口:,输出:,为了方便大家能更好看懂后面的源码,我先整体介绍一下源码的执行流程,让大家有一个整体的认识,否则容易被绕进去。,整个 Spring 事务源码,其实分为 2 块,我们会结合上面的示例,给大家进行讲解。61 张图,剖析 Spring 事务,就是要钻到底!,第一块是后置处理,我们在创建 Louzai Bean 的后置处理器中,里面会做两件事情:,获取 Louzai 的切面方法:首先会拿到所有的切面信息,和 Louzai 的所有方法进行匹配,然后找到 Louzai 所有需要进行事务处理的方法,匹配成功的方法,还需要将事务属性保存到缓存 attributeCache 中。,创建 AOP 代理对象:结合 Louzai 需要进行 AOP 的方法,选择 Cglib 或 JDK,创建 AOP 代理对象。,61 张图,剖析 Spring 事务,就是要钻到底!,第二块是事务执行,整个逻辑比较复杂,我只选取 4 块最核心的逻辑,分别为从缓存拿到事务属性、创建并开启事务、执行业务逻辑、提交或者回滚事务。,注意:Spring 的版本是 5.2.15.RELEASE,否则和我的代码不一样!!!,上面的知识都不难,下面才是我们的重头戏,让你跟着楼仔,走一遍代码流程。,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,这里需要多跑几次,把前面的 beanName 跳过去,只看 louzai。,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,进入 doGetBean(),进入创建 Bean 的逻辑。,61 张图,剖析 Spring 事务,就是要钻到底!,进入 createBean(),调用 doCreateBean()。,61 张图,剖析 Spring 事务,就是要钻到底!,进入 doCreateBean(),调用 initializeBean()。,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,如果看过我前面几期系列源码的同学,对这个入口应该会非常熟悉,其实就是用来创建代理对象。,61 张图,剖析 Spring 事务,就是要钻到底!,这里是重点!敲黑板!!!,先获取 louzai 类的所有切面列表;,创建一个 AOP 的代理对象。,61 张图,剖析 Spring 事务,就是要钻到底!,3.2.1 获取切面列表,61 张图,剖析 Spring 事务,就是要钻到底!,这里有 2 个重要的方法,先执行 findCandidateAdvisors(),待会我们还会再返回 findEligibleAdvisors()。,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,依次返回,重新来到 findEligibleAdvisors()。,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,进入 canApply(),开始匹配 louzai 的切面。,61 张图,剖析 Spring 事务,就是要钻到底!,这里是重点!敲黑板!!!,这里只会匹配到 Louzai.testSuccess() 方法,我们直接进入匹配逻辑。,61 张图,剖析 Spring 事务,就是要钻到底!,如果匹配成功,还会把事务的属性配置信息放入 attributeCache 缓存。,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,我们依次返回到 getTransactionAttribute(),再看看放入缓存中的数据。,61 张图,剖析 Spring 事务,就是要钻到底!,再回到该小节开头,我们拿到 louzai 的切面信息,去创建 AOP 代理对象。,61 张图,剖析 Spring 事务,就是要钻到底!,3.2.2 创建 AOP 代理对象,创建 AOP 代理对象的逻辑,在上一篇文章(Spring AOP)讲解过,我是通过 Cglib 创建,感兴趣的同学可以关注公众号「楼仔」,翻一下楼仔的历史文章。,回到业务逻辑,通过 louzai 的 AOP 代理对象,开始执行主方法。,61 张图,剖析 Spring 事务,就是要钻到底!,因为代理对象是 Cglib 方式创建,所以通过 Cglib 来执行。,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,这里是重点!敲黑板!!!,下面的代码是事务执行的核心逻辑 invokeWithinTransaction()。,61 张图,剖析 Spring 事务,就是要钻到底!,3.3.1 获取事务属性,在 invokeWithinTransaction() 中,我们找到获取事务属性的入口。,61 张图,剖析 Spring 事务,就是要钻到底!,从 attributeCache 获取事务的缓存数据,缓存数据是在 “2.2.1 获取切面列表” 中保存的。,61 张图,剖析 Spring 事务,就是要钻到底!,3.3.2 创建事务,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,通过 doGetTransaction() 获取事务。,通过 startTransaction() 开启事务。,61 张图,剖析 Spring 事务,就是要钻到底!,下面是开启事务的详细逻辑,了解一下即可。,最后返回到 invokeWithinTransaction(),得到 txInfo 对象。,61 张图,剖析 Spring 事务,就是要钻到底!,3.3.3 执行逻辑,还是在 invokeWithinTransaction() 中,开始执行业务逻辑。,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,进入到真正的业务逻辑。,61 张图,剖析 Spring 事务,就是要钻到底!,执行完毕后抛出异常,依次返回,走后续的回滚事务逻辑。,3.3.4 回滚事务,还是在 invokeWithinTransaction() 中,进入回滚事务的逻辑。,61 张图,剖析 Spring 事务,就是要钻到底!,。,61 张图,剖析 Spring 事务,就是要钻到底!,执行回滚逻辑很简单,我们只看如何判断是否回滚。,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,61 张图,剖析 Spring 事务,就是要钻到底!,如果抛出的异常类型,和事务定义的异常类型匹配,证明该异常需要捕获。,之所以用递归,不仅需要判断抛出异常的本身,还需要判断它继承的父类异常,满足任意一个即可捕获。,61 张图,剖析 Spring 事务,就是要钻到底!,到这里,所有的流程结束。,我们再小节一下,文章先介绍了事务的使用示例,以及事务的执行流程。,之后再剖析了事务的源码,分为 2 块:,先匹配出 louzai 对象所有关于事务的切面列表,并将匹配成功的事务属性保存到缓存;,从缓存取出事务属性,然后创建、启动事务,执行业务逻辑,最后提交或者回滚事务。

© 版权声明

相关文章