前言

在mybatis框架的整个架构中其实有一些在平时开发看来比较耗时的环节,如果在项目启动完成后在去初始化是性能和体验很不好的。比如:反射组件初始化、配置文件的解析和加载到内存、二级缓存模型的构建过程、日志组件的初始化等。还好这些mybatis都为我们考虑到了。今天我们就从mybatis框架的初始化开始聊聊项目启动时配置加载的话题。

核心运作流程

mybatis源码解析 - 核心流程之配置解析_第1张图片

我把mybatis的运作流程分为以上三个大的阶段:

首先是框架初始化阶段,这个阶段主要是mybatis-config.xml、properties、项目mapper.xml等配置文件的解析以及SqlSessionFactory的注入等;

然后是代理阶段,这个阶段在构建整个mybatis的Mapper开发模型,动态mapper代理对象的构建和增强、编程模式的封装和转换;

最后才是落地阶段,进行SQL的读写操作,包括SQL语句的映射、参数的映射、执行器的运作、结果集的映射、赋值、包装和最后返回等相关过程;


今天先从第一个阶段开始来剖析一下mybatis配置解析阶段的相关工作。

配置解析流程

mybatis源码解析 - 核心流程之配置解析_第2张图片

整个配置解析大体上分为七个核心步骤,其中请重点关注settings、plugins和mappers这几个解析阶段,而mappers的解析是重中之重。整个解析详细的过程我这边从代码的角度绘制了对象调用的时序图。

mybatis源码解析 - 核心流程之配置解析_第3张图片

上图红色和绿色字体的环节为比较重要处理节点,大家可以重点看一下这些点的源代码。下面我们就来逐一过一下

一、配置解析的入口

方式一、原生的mybatis开发,解析入口为SqlSessionFactoryBuilder-->build()方法

mybatis源码解析 - 核心流程之配置解析_第4张图片

方式二、若和spring结合,那解析的入口在这里

mybatis源码解析 - 核心流程之配置解析_第5张图片

二、Properties文件的解析

mybatis源码解析 - 核心流程之配置解析_第6张图片

原生支持两种方式的该文件解析来源:1.以项目resource的方式配置文件路径;2.以url磁盘路径的方式只是资源文件所在位置; 解析的结果以properties对象的形式存入全局配置对象Configuration

三、Settings配置详解

mybatis源码解析 - 核心流程之配置解析_第7张图片

我们项目中常用的配置是:cacheEnabled二级缓存开关 / lazyLoadingEnabled延迟加载开关 / aggressiveLazyLoading同步加载开关 / useGeneratedKeys使用主键key开关 / mapUnderscoreToCamelCase自动驼峰转换开关等。其它参数在你的项目中特定的使用场景可能需要配置都统一过一遍。

四、环境节点解析

mybatis源码解析 - 核心流程之配置解析_第8张图片

注意:在通过applicationContext.xml方式注入,并配置数据源后。以上环境节点在mybatis-config.xml中的配置将全部被忽略!!

五、plugins插件的解析

mybatis源码解析 - 核心流程之配置解析_第9张图片

支持多自定义拦截器插件配置和初始化,最终的结果放入全局Configuration配置对象中

六、重点:mappers节点解析

mybatis源码解析 - 核心流程之配置解析_第10张图片

mybatis的mapper.xml的解析默认支持四种不同的来源方式:1. 来源于jar包;2.来源项目resource目录;3.来源于url路径;4.来源于指定的mapper接口;

这四种来源的文件解析顺序为:解析来源jar包--->来源resource路径下xml--->来源本地磁盘路径下xml---->来源指定的Mapper接口,也就是说我们可以同时配置,多种来源的mapper.xml;

mappers节点核心的解析过程被封装到了XMLMapperBuilder中,它的解析流程为:

mybatis源码解析 - 核心流程之配置解析_第11张图片

1. 总体解析算法

mybatis源码解析 - 核心流程之配置解析_第12张图片

在configurationElement方法中对maper.xml中的所有节点详细进行解析,读到的xml文件缓存到configuration的资源块中,最后对在前面解析失败的节点resultMap、cache-ref、curd(insert/update/delete/select)等进行补偿性的再次解析(再解析失败,则忽略异常)。

2. 解析二级缓存

mybatis源码解析 - 核心流程之配置解析_第13张图片

mybatis源码解析 - 核心流程之配置解析_第14张图片

这里采用建造者模式进行二级缓存的组合创建,根据配置创建成功的缓存对象,直接放入全局配置对象

mybatis源码解析 - 核心流程之配置解析_第15张图片

mybatis源码解析 - 核心流程之配置解析_第16张图片

采用装饰器模式,为二级缓存添加各种能力。默认支持SerializedCache / LoggingCache / SynchronizedCache / PrepetureCache等这些二级缓存特性,BlockingCache能力默认是不加上的。

3. 解析resultMap

mybatis源码解析 - 核心流程之配置解析_第17张图片

mybatis源码解析 - 核心流程之配置解析_第18张图片

4. 解析crud(insert / update /delete /select)等节点

mybatis源码解析 - 核心流程之配置解析_第19张图片

mybatis源码解析 - 核心流程之配置解析_第20张图片

mybatis源码解析 - 核心流程之配置解析_第21张图片

这里解析sql语句的代码封装比较深,代码有点繁杂,但没有太多的技术难度。这里就不深入进去了。说一下重点mappers节点的每个mapper子节点解析的结果都放入了Configuration全局对象中的mappedStatement, 它是一个Map

key就是(namespace+命令id), Value为MappedStatement对象。

mybatis源码解析 - 核心流程之配置解析_第22张图片

mappedStatement中包含这些对象,这些对象和xml的一一对应关系是:

mybatis源码解析 - 核心流程之配置解析_第23张图片


根据上面的截图,结合大家平时的开发,大家应该对mappedStatement的数据结构应该有了一个比较直观的了解了吧?下面我们把整个配置文件解析的最重要目标成果展示一下。让大家对configuration的骨架有一个全面直观的认识。

mybatis源码解析 - 核心流程之配置解析_第24张图片


总结

以上就是mybatis配置文件解析的全过程和目标成果。我的理解学习源码更重要的是理顺和掌握核心设计的流程,而不是扣某个代码的细节。大家如果有mybatis的任何问题,欢迎在屏幕下方留言,大家一起讨论!下次我们将解析mapper编程模型构建的过程,请继续关注!