MyBatis初始化阶段

MyBatis主要有三大核心流程

  • 初始化阶段: 读取XML配置文件和注解中的配置信息,创建配置对象,并完成各个模块的初始化的工作
  • 代理阶段: 封装iBatis的编程模型,使用mapper接口开发的初始化工作
  • 数据读写阶段: 通过SqlSession完成SQL的解析,参数的映射、 SQL的执行、结果的解析过程

这里我们主要来说一说我们MyBatis的初始化阶段,也就是我们MyBatis进行配置加载的阶段,我们看看我们MyBatis是如何把我们的配置文件以及Mapper文件进行加载的。
在这里插入图片描述
Configuration: Mybatis启动初始化的核心就是将所有xml配置文件信息加载到Configuration对象中, Configuration是单例的,生命周期是应用级的

在这里插入图片描述
在这里插入图片描述



Configuration

从上图中,我们可以发现其实我们MyBatis初始化的阶段就是为了创建我们的Configuration,首先我们需要将我们的MyBatis的核心配置文件给加载到Configuration中去。


我们会发现我们在MyBatis配置文件中配置的所有信息,也就是我们的 MyBatis配置 中介绍的所有配置信息,我们在Configuration类中都可以找到对应的地方。
在这里插入图片描述



XMLConfigBuilder

我们来看看我们在 初识MyBatis 中测试MyBatis的代码


我们发现其就使用到了我们的 建造者模式 ,其实我们MyBatis在初始化阶段很多地方都使用到了建造者模式,我们也介绍过建造者模式的特点,注重的是部件构建的过程,建造者模式是通过一步一步地精确构造创建一个复杂的对象,刚好符合我们每个人的配置文件可能有所不同。
在这里插入图片描述

我们来看看它是如何进行解析MyBatis的配置文件的
在这里插入图片描述

我们发现它会先判断下这个配置文件是否已经加载过了,若是没有的话,我们就找到其根节点进行解析
在这里插入图片描述
在这里插入图片描述

进入其解析方法后,发现它就是一一解析我们配置文件中的各个节点
在这里插入图片描述

我们这里以解析properties节点为例,我们会发现有没有子节点,我们properties也可以直接将一些信息用子节点配置在里面的,然后再取一些节点里设置属性信息,判断有没有,有的话进行加载,最后是会将其加载到Configuration之中去的。
在这里插入图片描述



XMLMapperBuilder

上述看完了XMLConfigBuilder加载我们的MyBatis配置信息,这里我们再来看看我们的XMLMapperBuilder是如何加载我们的Mapper文件信息的。


我们的Mapper文件信息,也是会配置在MyBatis配置文件中的,我们之前在 MyBatis配置 还介绍过好几种方法,如下:
在这里插入图片描述

既然在MyBatis配置文件中,那么肯定会被我们刚刚说的XMLConfigBuilder所解析
在这里插入图片描述

这里我们就看一种我们平常最经常用的,看看其是如何解析的。
在这里插入图片描述

这里它也是会先判断下文件是否已经加载过了,若是没有的话,我们就找到其根节点进行解析
在这里插入图片描述
在这里插入图片描述

进入其解析方法后,发现它就是一一解析我们配置文件中的各个节点,然后加入到我们的Configuration中去
在这里插入图片描述


由于这里我们之前介绍过 MyBatis 缓存MyBatis缓存模块分析 ,所以这里我们就以解析缓存为例


里面就是解析 <cache> 标签里面的属性,我们在 MyBatis 缓存 几乎已经都介绍过了,也说过如何配置,就是一个之前没有说,它就设置了缓存的类型,我们在 MyBatis缓存模块分析 中介绍了好几种,这里就是可以配置其类型,它默认的就是没有通过装饰模式修饰的最基础的缓存类。最后在通过我们辅助类builderAssistant来加入到我们的Configuration之中
在这里插入图片描述

它使用到了建造者模式进行创建一个缓存对象,并且我们知道这配置的是二级缓存,我们的二级缓存是通过namespace进行区别的
在这里插入图片描述

所以它是一个以键值对的形式进行存储,就是一个Map
在这里插入图片描述
在这里插入图片描述




这里我们再来看一看解析 resultMap 标签,因为这个标签我们在Mapper文件中使用的频率非常的高
在这里插入图片描述

我们在一个Mapper文件中可能有多个resultMap,所以这里我们需要遍历的去解析
在这里插入图片描述

我们会先解析一些resultMap里面设置的一些属性,这里很多我们都使用过,如下
在这里插入图片描述
在这里插入图片描述

解析完resultMap标签里的属性,我们再看看其中的子标签,如
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

我们知道resultMap里面肯定有多行子标签,它会去判断是构造器、还是鉴别器,还是我们用来映射字段信息的
在这里插入图片描述

最后我们会把所有解析resultMap的结果都会有我们的辅助类builderAssistant进行处理
在这里插入图片描述

里面通过了建造者模式生成出ResultMap,然后添加到Configuration之中。
在这里插入图片描述
在这里插入图片描述

它的key是有Mapper的namespace命名空间加上了resultMap的id组成的,这样就可以唯一对应的一个ResultMap
在这里插入图片描述

我们来看看我们用于存储resultMap信息的数据结构ResultMap,就是保存上述我们解析完得到结果的类


我们可以看到该数据结构中,保存了resultMap中可以设置的所有属性值,如id、所要映射的Java对象类型,还有一些鉴定器等等,我们还发现里面还有一些分类的List,里面保存就ResultMapping的数据结构主要是为了存储resultMap下的行信息
在这里插入图片描述

如我们经常用到的一些行属性,以及一对多时使用到的属性
在这里插入图片描述



XMLStatementBuilder

刚刚我们说了XMLMapperBuilder帮助我们解析了Mapper文件,现在我们Mapper文件中只有SQL语句没有进行解析了,现在我们就主要看看其SQL语句的解析。
在这里插入图片描述
在这里插入图片描述

里面就是对我们SQL语句中的一些属性进行解析
在这里插入图片描述

这里就是对我们SQL语句执行的类型,我们之前说过前两中,就是直接拼接和预编译的区别,这里默认的是预编译设置,第三个就和存储过程有关。
在这里插入图片描述
在这里插入图片描述

这是判断下我们SQL语句的类型,是增删改查中的哪一种
在这里插入图片描述
在这里插入图片描述

这里就是为了处理我们include标签引入的 sql 的SQL语句,以及处理我们 selectKey标签等,处理完成后我还需要将其删除,最后我们解析SQL语句,得到SqlSource
在这里插入图片描述

里面存储的就是我们处理完后的SQL语句,以及这里占位符需填充的参数
在这里插入图片描述
在这里插入图片描述

下面就是我们判断是否是 INSERT 语句,是的话,我们又配置了 userGeneratedKeys ,这里我们就会去拿到其生成的主键
在这里插入图片描述

最后我们就是将上述得到的结果,全部交由辅助类builderAssistant去处理
在这里插入图片描述

里面我们通过了建造者模式生成出MappedStatement,然后添加到Configuration之中。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

最后我们在来看看建造者生成的MappedStatement,里面就是封装了一系列信息,有些就是我们上述所介绍的
在这里插入图片描述



最后我们要看一下就是我们的Mapper文件解析完成之后,就是我们的XMLMapperBuilder、XMLStatementBuilder处理完成之后,也就是我们的Mapper文件全部解析好了,我们看看之后的操作


我们就将这个的结果也放到Configuration里面,并且还要去注册Mapper接口
在这里插入图片描述
在这里插入图片描述

最后我们有可能还有解析失败的,所以我们再将解析失败的再尝试解析一下进行处理
在这里插入图片描述