浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

前言

在上一篇中,我们介绍了在SpringBoot容器中,Mybatis加载mapper interface的过程,但对于mapper加载的全过程,这仅仅完成了50%,剩下的50%就是mapper的关联SQL配置的加载过程,本篇,我们将围绕下面两个问题进行展开:

1、mapper的关联SQL配置是如何进行加载的?

2、Mybatis是如何将mapper interface与SQL配置关联在一起的?

Mybatis加载Mapper关联SQL配置

首先,我们先来回顾一下mapper interface的加载过程:

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

上面的流程图就是Mybaits加载mapper interface的全流程,其实,mapper关联的SQL配置的加载过程就包含在其中,我们以MapperFactoryBean作为切入点,来分析一下。

MapperFactoryBean

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

MapperFactoryBean从名字中我们就可以看出来,这是一个Mapper bean的工厂类,它继承了SqlSessionDaoSupport类并实现了FactoryBean接口,具备了FactoryBean的能力。

在SpringBoot初始化mapper bean的过程中,会调用checkDaoConfig方法,在方法中,首先会检查mapper interface是否已经完成了初始化,如果没有,则进行初始化,我们继续进入configuration.addMapper(this.mapperInterface)看看其实现:

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

调用了ConfigurationaddMapper方法,我们继续。

MapperRegistry

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

OK,最终进入了MapperRegistryaddMapper方法,进行最终的加载,在MapperRegistry中,存储了已经加载完成的mapper interface的Map容器,在addMapper方法中,会进行两步操作:

1、检查mapper interface是否在初始化好的容器列表中;

2、如果没有,则放入容器列表中,然后初始化关联的mapper annotation或XML配置信息。

看到这里,我们大概清楚mapper的SQL关联配置真正的加载实现所在了,我们继续深入。

MapperAnnotationBuilder

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

真正的解析配置的动作是由MapperAnnotationBuilderparse方法执行的,在分析其实现之前,我们先来看一下这个类所在的目录结构:

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

上图是Mybatis项目的目录结构,可以看到,MapperAnnotationBuilder所属与builder包下,在该包下,存在两个子目录结构,分别是annotationxml,看到这里,想必您肯定也一目了然,这正是对应了Mybatis的两种mapper关联SQL配置的方式,换句话说,就是两种书写SQL语句的方式,而默认的情况下,SpringBoot加载Mybaits是使用MapperAnnotationBuilder作为解析入口。

OK,我们继续分析MapperAnnotationBuilderparse方法的实现:

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

上图是MapperAnnotationBuilderparse方法实现内容,主要分为五个部分:

1、获取mapper interface全路径限定名称;

2、检查mapper interface是否已经加载过;

3、如果没有加载,尝试加载关联的XML配置文件;

4、将mapper interface加入到已加载列表中;

5、遍历mapper interface中的全部方法,进入annotation加载流程。

我们来重点分析其中关键两个部分,XML配置的加载过程与annotation配置的加载过程,首先来看XML配置的加载过程。

XML配置解析加载过程

XMLMapperBuilder

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

进入loadXmlResource方法,其中主要进行了两步操作:

1、根据mapper interface的全限定路径名称,寻找classpath下同名的XML文件;

2、解析加载XML文件。

我们继续深入:

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程
浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

XML的解析过程可以如上图所示,首先仍是判断该mapper interface是否已经加载过,如果没有,开始对XML配置中的标签进行逐个解析,详细的解析过程我们就不深入分析了,主要是解析XML的DOOM树结构,获取标签中的具体内容,需要关注的是解析过程中的最后一个方法:buildStatementFromContext

XMLStatementBuilder

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

进入statementParser.parseStatementNode()

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程
浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

实现比较长的一个方法,不过其实现内容可以一目了然,主要是对XML配置文件中的各个标签进行解析的过程,重点关注的是在方法的最后,执行的builderAssistant.addMappedStatement方法。

MapperBuilderAssistant

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

builderAssistant.addMappedStatement方法的实现如上图所示,在其中通过MappedStatement.Builder的构造器构造出一个statementBuilder对象,存入ConfigurationmapperStatement的Map集合中,而这个Map集合的key,就是XML配置文件中的<id>中的属性值。

MappedStatement对象,其中则存储了mapper interface对应的SQL语句,mapper interface与SQL的关联关系,正是通过mapper interface的全限定路径名称进行关联的

但在SpringBoot加载mapper interface关联的XML配置文件的过程,其实并不是在这里进行的,而是在SqlSessionFactoryBean中进行加载的,我们来看一下其实现。

SqlSessionFactoryBean

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

SqlSessionFactoryBean实现了InitializingBean接口,实现了afterPropertiesSet方法,在bean初始化的时候会调用该方法,在afterPropertiesSet中,调用了buildSqlSessionFactory方法:

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

我们主要关注下面的实现:

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

mapperLocations是通过SpringBoot的application.properties文件中的mybatis.mapper-locations参数注入进来的,这里会扫描XML配置文件所在目录下的全部XML配置文件,并逐一解析,完成加载过程。

OK,XML配置文件的加载过程我们就分析完毕,再回头看一下annotation配置的加载过程。

Annotation配置解析加载过程

上面我们先分析了XML配置文件的加载与关联mapper interface的过程,下面我们再看一下Annotation的加载过程:

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

我们来看上图中的第五步,这里会遍历mapper interface中的全部方法列表,逐个进行解析,在解析之前,有一个isBridge的判断,判断该方法是否是桥接方法,那么什么是桥接方法呢?简单的说,就是由Java编译器隐式的自动生成的一种方法,具体的解析可以参见:

Java反射中method.isBridge() 桥接方法:https://blog.csdn.net/liu20111590/article/details/81294362

进入parseStatement方法实现:

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程
浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

看到这里,是不是有种还是原来的配方,还是原来的味道的感觉?没有错,这里的解析过程与XML配置文件的解析过程非常相似,对方法上的@Annotation进行逐个解析,最终生成一个MappedStatement对象。

加载Mapper关联SQL配置全流程

浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程

结语

本篇,我们介绍了Mybatis加载Mapper关联SQL配置的整个过程,现在也可以解释文章开头的两个问题:

1、mapper的关联SQL配置是如何进行加载的?

2、Mybatis是如何将mapper interface与SQL配置关联在一起的?

整个加载过程非常的冗长,建议您看完本篇后,可以下载一下mybatis3与mybatis-spring的项目源码,跟着我的思路,一步一步走一遍,相信您也会有非常大的收获。

对于Mybatis的整个初始化流程就介绍完毕了,那么又来了新的问题,Mybaits是如何执行一条SQL语句的?在下一篇中,我们会揭开这个答案,敬请期待!

感谢您的阅读。

更多精彩文章, 请关注我的个人公众号:老宣说
让我们一起共同学习成长!
感谢您的支持!
浅入浅出Mybatis:(三)Mapper关联SQL配置加载过程