该系列文章针对 Mybatis 3.5.1 版本
上一篇文章提到,针对 mybatis-config.xml XML 配置中的 <mappers> ,Mybaits 主要会加载两个模块的数据
- 1、 XML 文件
- 2、 mapper class 接口文件
来回顾一下 mybatis-config.xml 中 <mappers> 的配置示例,如下图:
如图,有两种配置方式,
一种:单独配置,通过 <mapper resource="xml路径">配置。多个 xml 文件,就有多个配置
一种:扫包配置,通过 <package name="xml.mapper"/> 配置,配置 xml 文件所在的包路径,让程序扫包配置
再来回顾一下,XMLConfigBuilder 解析时序简图,如下:
在时序图中 <mappers> 加载解析在 XMLConfigBuilder#mapperElement 中完成,相关解析代码如下:
如上述代码,针对 <mappers> 子标签的解析分为两种:扫包批量解析和单个文件解析。
而无论是扫包批量解析亦或者单个文件解析,都会对 xml 文件 和 class 文件进行解析处理。
本章,主要来讨论 mapper class 接口文件的加载,这里以 <mapper> 单个的加载为例,<package> 扫包方式类似可以自行查阅。
扫包的方式,不支持 xml 文件的 SQL 管理,仅支持
@Select注解式的 SQL
<mapper> 单文件加载分析
先来看一下 XMLConfigBuilder 的解析入口,如下:
如上述代码所示,针对 <mapper> 标签属性读取一共有三个,分别是:resource,url 和 class
其中 resource 和 url 配置的是 xml 文件路径,resource 对应的是本地项目路径,url 对应的远程文件路径。 resource 、 url 和 class 属性配置在加载完xml文件后,同时也会加载相应的 class 类文件,并解析 class 类文件中的注解式的 SQL 语句。
针对本次章节讨论的 mapper class 文件解析,无论是 resource 、 url 和 class 属性配置,最后都会进行处理,mapper class 文件最终处理调用的是 Configuration#addMappers 代码。
关于 XML 文件的加载解析,在下一篇文章中展开
Configuration#addMappers 方法代码如下
通过 Configuration#addMappers 能够看到一个容器类 MapperRegistry,该容器类存放了所有加载之后的 Mapper.class 内容,
MapperRegistry和前面提到的TypeAliasRegistry和TypeHandlerRegistery一样都是用来存储 Mybatis 特定内容的容器。
来看一下 Mapper class 文件注册到 MapperRegistry 容器的代码, MapperRegistry#addMapper 。
通过上述代码整理 mapper class 解析流程判断如下:
1、Mapper.class 必须是一个接口
2、Mapper.class 会以代理对象的形式存储于 MapperRegistry#knownMappers 中,该代理对象为 MapperProxyFactory
3、Mapper.class 中方法上的 @Select 等注解解析通过 MapperAnnotationBuilder 完成。
从上述流程能够再将 mapper class 解析后的数据分为两部分:
一部分:mapper class 本身对应的代理类工厂 MapperProxyFactory ,该信息存储在 MapperRegistry#knownMappers 中
一部分:mapper class 方法函数上对应的注解,所绑定的 SQL
关于 Mapper.class 中
@Select等注解的解析,将会在下一章和 Mapper xml 中<select>等标签解析一起讲解
Mapper.class代理对象MapperProxy的使用将在核心业务层,进行数据访问调用时展开。
Mybatis 运行框架图
Mybatis 在加载 mapper class 文件后,会将其通过 MapperProxyFactory 代理工厂进行包装,然后存放在 MapperRegistry 中,同时会将 MapperRegistry 以属性对象的形式,存储在 Configuration 对象中。
完善对应的运行框架图,如下:
【公众号】花好夜猿