Mybatis对mapper的加载流程深入讲解
作者:IT乐知 发布时间:2022-06-01 12:33:04
今天来分析Configuration初始化的最后一部分mapper的加载。
加载方法mapperElement
XMLConfigBuilder配置Configuration的parseConfiguration方法还剩最后一行解析代码:mapperElement(root.evalNode("mappers"));
mapperElement方法源码与详解如下图:
从源码可以得出一些结论:
mappers节点支持mapper和package两种类型子节点;
package子节点只需要name一个属性;
一个mapper子节点有且只能有url、resource、class三个属性中其中一个,否则会抛出异常;
mapperElement解析两种mappers子节点,主要代码我分成了4个部分,接下来逐一进行深入解析。
解析包方法addMappers
首先来看解析包的方法使用的是configuration的addMappers方法,方法主要是涉及到一个MapperRegistry类型的属性mapperRegistry,addMappers主要流程如下图:
addMappers方法主要涉及到的是MapperRegistry这个类,这个类有两个属性:config、knownMappers。 在config指向的是configuration,knownMappers存放这class文件对应的MapperProxyFactory 。 MapperProxyFactory根据名字先猜测是创建mapper代理的工厂。
介绍完关键类,再来看addMappers主要分4步:
调用mapperRegistry属性的addMappers(String packageName)方法这个方法会调用另外一个addMappers;
addMappers(String packageName, Class<?> superType)方法会遍历指定包下面所有属于superType子类的类,上一步传递的是Object.class,所以这里是遍历所有类,然后调用addMapper(mapperClass)方法;
addMapper(mapperClass)方法首先需要判断mapperClass必须是接口, 再判断class是否已经存在,存在会报异常 。不存在则实例化一个MapperProxyFactory对象并put进knownMappers,最后根据class创建一个MapperAnnotationBuilder并调用parse方法。
最后是MapperAnnotationBuilder的parse方法,MapperAnnotationBuilder是解析mapper注解的,我们后面详解。
加载package下的mapper总的流程看下来比较简单,实际上就是 找到对应包下面所有的接口,然后根据接口创建一个MapperProxyFactory放到configuration属性mapperRegistry的knownMappers中 。
解析单个mapper
从解析单个mapper有三种情况,但是分两种情况,一种是有resource或者url属性的是直接根据属性值生成一个XMLMapperBuilder对象,然后执行parse方法,如果是由class属性值和加载包的最后一步方法相似,调用mapperRegistry的addMapper方法。
XMLMapperBuilder的初始化和parse简单介绍源码如下图:
解析mapper.xml的XMLMapperBuilder和最开始解析mybatis-config.xml的XMLConfigBuilder一样都是继承至mybatis的BaseBuilder,并且初始化流程也差不多。
可以看出XMLMapperBuilder类是解析mapper.xml最关键的类,这个类比较复杂,接下来的文章再来专门讲解它。
总结
mapper的注入支持两种方式,单个mapper注入或者整个包下面注入,也可以按加载class文件或者xml文件分成两种。单个mapper注入如果是根据url或者xml则是通过加载xml文件注入,通过url获取扫描整个包加载则是class方式进行注入。
通过xml加载是直接根据xml生成XMLMapperBuilder,然后执行parse方法。
通过class加载则是接口类生成MapperProxyFactory,放到MapperRegistry的map属性knownMappers中,最后通过MapperAnnotationBuilder执行parse进行解析,parse也会调用XMLMapperBuilder的parse方法。
后面的文章我们先解读MapperAnnotationBuilder这个类,最终再来看最重要的类XMLMapperBuilder。
从目前源码可以得出一些需要注意的点:
一个mapper子节点有且只能有url、resource、class三个属性中其中一个,否则会抛出异常;
一个mapper只能被加载一次,重复加载会抛出异常。
来源:https://juejin.im/post/6895557869841121293


猜你喜欢
- idea中创建一个maven项目在pom文件中导入下面的依赖<!--mybatis核心包--> <depend
- 使用System.Environment获取电脑的相关属性,入门案例,具体内容如下static void Main(string[] arg
- 前言RedisTemplate是Spring对于Redis的封装。如上图所示,RedisTemplate中定义了对5种数据结构操作。redi
- spring 容器的创建对应 SpringApplication 中 run 中调用的 createApplicationContext 方
- 基于创蓝253短信服务平台的Java调用短信接口APIpackage com.bcloud.msg.http;import java.io.
- 实现定时器有很多种方式,在这里我简单的介绍几种方式 (1)使用Handler + Runnable的方式 Handler handler =
- 此例子,用于说明如何在Java中对“注解 Annotation”的定义、使用和解析的操作。注解一般用于自定义开发框架中,至于为什么使用,此处
- 很多时候我们用HTML布局会更方便直接,记录一下。我现在主要是直接调用服务器的网页(实际上是jsp的,只是返回的是html),所以需要联网,
- 一、实现原理使用MockMvc发起请求,然后执行API中相应的代码,在执行的过程中使mock模拟底层数据的返回,最后结果验证。二、常用注解介
- Condition的作用是对锁进行更精确的控制。Condition中的await()方法相当于Object的wait()方法,Conditi
- 前段时间在看属性动画,恰巧这个按钮的效果可以用属性动画实现,所以就来实践实践。效果基本出来了,大家可以自己去完善。首先看一下效果图:我们看到
- 1、CyclicBarrier:一个同步辅助类,用于协调多个子线程,让多个子线程在这个屏障前等待,直到所有子线程都到达了这个屏障时,再一起继
- idea乱码修改bin目录下的idea.exe.vmoptions无效今天在学习Activiti工作流的时候,发现创建bpmn文件总是出现中
- 本文实例为大家分享了WPF实现3D翻牌式倒计时的具体代码,供大家参考,具体内容如下实现效果如下:思路:使用自定义控件,设置一个背板 MyCa
- 定时任务技术趋势简介:定时任务是每个业务常见的需求,比如每分钟扫描超时支付的订单,每小时清理一次数据库历史数据,每天统计前一天的数据并生成报
- 创建一个类,在该类的主方法中创建标准输入流的扫描器对象,提示用户输入一个整数,并通过扫描器的方法来接受这个整数,然后通过三元运算符判断该数字
- 1、比较器①比较器的引入a.首先,当我们单一地比较某一种数据类型的数组时,可以直接用Arrays.sort()进行实现b.而当我们同时含有多
- 因为在framework中想添加这个功能,所以写了个appliction来实现一下获取正在运行的应用程序: 还是先看图吧: 这个app主要是
- 进阶JavaSE-三大接口:Comparator、Comparable和Cloneable。Comparable和Comparator这两个
- 概述在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的。也就是说,程序的流程对运行结果有直接的影响。所以,我们必须清楚每条