mybatis源码分析-映射文件解析
在 mybatis源码分析-配置文件解析过程 一文中,主要对配置文件解析过程做了讲解,并且针对插件的配置文件做了详细讲解,本文主要对 mapper 映射文件的解析进行讲解。
mapper文件的加载
首先我们看下mybatis官网,看下mapper文件如何被全局配置文件加载的。下面是官网的说明:
既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要定义 SQL 映射语句了。 但是首先我们需要告诉 MyBatis 到哪里去找到这些语句。 Java 在自动查找这方面没有提供一个很好的方法,所以最佳的方式是告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用, 或完全限定资源定位符(包括file:///的 URL),或类名和包名等。例如:
<!-- 使用相对于类路径的资源引用 --> <mappers> <mapper resource="org/mybatis/builder/AuthorMapper.xml"/> <mapper resource="org/mybatis/builder/BlogMapper.xml"/> <mapper resource="org/mybatis/builder/PostMapper.xml"/> </mappers>
<!-- 使用完全限定资源定位符(URL) --> <mappers> <mapper url="file:///var/mappers/AuthorMapper.xml"/> <mapper url="file:///var/mappers/BlogMapper.xml"/> <mapper url="file:///var/mappers/PostMapper.xml"/> </mappers>
<!-- 使用映射器接口实现类的完全限定类名 --> <mappers> <mapper class="org.mybatis.builder.AuthorMapper"/> <mapper class="org.mybatis.builder.BlogMapper"/> <mapper class="org.mybatis.builder.PostMapper"/> </mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 --> <mappers> <package name="org.mybatis.builder"/> </mappers>
上面是mybatis所支持的mapper文件的编写方式,我们下面从源码角度研究一下。
mapper文件解析源码
首先了解一点,我们需要把接口全部加载到 MapperRegistry
类中,使用map保存。
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();
这个 MapperRegistry
类暂时不讲,以后会详细讲解。只要知道 Configuration
类有 addMapper
方法可以把接口加入到上面的 map 中即可。下面看具体源码:
private void mapperElement(XNode parent) throws Exception { if (parent != null) { for (XNode child : parent.getChildren()) { if ("package".equals(child.getName())) { //① String mapperPackage = child.getStringAttribute("name"); configuration.addMappers(mapperPackage); } else { String resource = child.getStringAttribute("resource"); String url = child.getStringAttribute("url"); String mapperClass = child.getStringAttribute("class"); if (resource != null && url == null && mapperClass == null) { //② ErrorContext.instance().resource(resource); InputStream inputStream = Resources.getResourceAsStream(resource); XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments()); mapperParser.parse(); } else if (resource == null && url != null && mapperClass == null) { //③ ErrorContext.instance().resource(url); InputStream inputStream = Resources.getUrlAsStream(url); XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments()); mapperParser.parse(); } else if (resource == null && url == null && mapperClass != null) {// ④ Class<?> mapperInterface = Resources.classForName(mapperClass); configuration.addMapper(mapperInterface); } else { throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one."); } } } } }
- ①如果配置文件使用的是使用 package 方式,需要把该包下面的所有接口都存入 map 中。
- ②如果配置是resource方式,则获取到 mapper 映射文件的路径,然后解析这些文件,注意解析生成的是
XMLMapperBuilder
对象,而不是XMLConfigBuilder
对象。XMLMapperBuilder
对象的parse方法就可以进行将mapper文件进行解析。 - ③如果配置是url方式,同 resource。
- ④如果配置的是 class ,那么直接存入 map ,无需解析。这种方式使用 mapper 接口替代 mapper映射文件的配置方式。
上面不管使用什么方式,都需要在加载全局配置文件的时候,将我们所定义的接口先缓存起来,以便后面接口的调用。但是上面4种配置方式大致可以分为 2 种,一种直接找 mapper xml 配置文件,一种是找接口或者包(包其实下面也是接口)。
本节暂时不讲解那么多,后面章节主要讲解这两种方式。不过可以首先透漏下:
- 对于 接口或者包 的形式,主要讲解的代码是
- 对于其它两种方式
主要是XMLMapperBuilder
的研究。
原文地址:https://segmentfault.com/a/1190000021417993
相关推荐
-
面试高频:深入理解Java虚拟机之—JVM类加载过程和类加载器 Java基础
2020-6-14
-
通过软引用和弱引用提升JVM内存使用性能的方法(面试时找机会说出,一定能提升成功率) Java基础
2019-6-3
-
阿里巴巴泰山版《Java 开发者手册》,也是一份防坑指南 Java基础
2020-6-13
-
ES&IK环境搭建 Java基础
2019-7-22
-
Java8新特性(1):Lambda表达式 Java基础
2020-6-13
-
互联网 Java 工程师面试题系列(Elasticsearch 面试题) Java基础
2020-6-14
-
Vert.x Blueprint 系列教程(二) | 开发基于消息的应用 – Vert.x Kue Java基础
2020-5-30
-
7. 初步理解面向对象 【连载 7】 Java基础
2020-5-30
-
从构建分布式秒杀系统聊聊商品详情页静态化 Java基础
2019-3-13
-
多线程编程(一)– 揭开线程的神秘面纱 Java基础
2019-7-8