Mybatis源码解析(四)-配置加载初始化(建造者模式)

@[TOC] 配置加载初始化—》 建造者模式
#MyBatis 在我们的开发中,主要是各种配置文件是特别多,包括mybatis-config.xml和各种mapp.xml文件,这些配置文件是程序启动的时候加载到内存中,并且实例化mybatis相关的实例对象,这个实例化,解析的过程是非常复杂。主要涉及SqlSessionFactoryBuilder,XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder、ResultMapping.Builder等解析器。针对这个复杂的对象构造过程,mybatis也是巧妙的使用了建造者模式来实现。

part1:建造者模式

	建造者模式(BuilderPattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。建造者模式类图如下:

Mybatis源码解析(四)-配置加载初始化(建造者模式)_第1张图片
Product:要创建的复杂对象
 Builder:给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要
实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建;
 ConcreteBuilder:实现 Builder 接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例;
 Director:调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的
信息,只负责保证对象各部分完整创建或按某种顺序创建;
建造者使用场景:
需要生成的对象具有复杂的内部结构,实例化对象时要屏蔽掉对象内部的细节,让上层代码与复杂对象的实例化过程解耦,可以使用建造者模式;简而言之,如果“遇到多个构造器参数时要考虑用构建器”;
对象的实例化是依赖各个组件的产生以及装配顺序,关注的是一步一步地组装出目标对象,可以使用建造器模式;
Mybatis源码解析(四)-配置加载初始化(建造者模式)_第2张图片

part2:配置加载的核心类

在 MyBatis 中负责加载配置文件的核心类有三个,类图如下:
Mybatis源码解析(四)-配置加载初始化(建造者模式)_第3张图片
BaseBuilder:所有解析器的父类,包含配置文件实例,为解析文件提供的一些通用的方法;
 XMLConfigBuilder: 主要负责解析 mybatis-config.xml;
 XMLMapperBuilder: 主要负责解析映射配置 Mapper.xml 文件;
 XMLStatementBuilder: 主要负责解析映射配置文件中的 SQL 节点;
XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder 这三个类在配置文件加载
过程中非常重要,具体分工如下图所示
Mybatis源码解析(四)-配置加载初始化(建造者模式)_第4张图片
配置加载过程首先会加载mybatis-config.xml,这里面涉及一个重要的对象,就是Configuration,这个对象可以说基本上包含了所有的配置:
Mybatis源码解析(四)-配置加载初始化(建造者模式)_第5张图片
这里介绍一下Configuration 对象的关键属性:
MapperRegistry:mapper 接口动态代理工厂类的注册中心。在 MyBatis 中,通过mapperProxy 实现 InvocationHandler 接口,MapperProxyFactory 用于生成动态代理的实
例对象;
 ResultMap:用于解析 mapper.xml 文件中的 resultMap 节点,使用 ResultMapping 来封装id,result 等子元素;
 MappedStatement:用于存储 mapper.xml 文件中的 select、insert、update 和 delete 节点,同时还包含了这些节点的很多重要属性;
 SqlSource:用于创建 BoundSql,mapper.xml 文件中的 sql 语句会被解析成 BoundSql 对象,经过解析 BoundSql 包含的语句最终仅仅包含?占位符,可以直接提交给数据库执
行;
需要特别注意的是 Configuration 对象在 MyBatis 中是单例的,生命周期是应用级的,换句话说只要 MyBatis 运行 Configuration 对象就会独一无二的存在
在 MyBatis 中仅在下面这个地方实例化
Mybatis源码解析(四)-配置加载初始化(建造者模式)_第6张图片
Configuration 对象的初始化(属性复制),是在建造 SqlSessionfactory 的过程中进行的
Mybatis源码解析(四)-配置加载初始化(建造者模式)_第7张图片
下面来详细讲解整个解析过程:整个过程主要有四个步骤
Mybatis源码解析(四)-配置加载初始化(建造者模式)_第8张图片
第一步: 通过 SqlSessionFactoryBuilder 建造 SqlSessionFactory,并创建XMLConfigBuilder 对象 读 取 MyBatis 核 心 配 置 文 件 , 见 方 法 :
org.apache.ibatis.session.SqlSessionFactoryBuilder.build(Reader, String, Properties),如下图:
Mybatis源码解析(四)-配置加载初始化(建造者模式)_第9张图片
第二步: 进入 XMLConfigBuilder 的 parseConfiguration 方法,对 MyBatis 核心配置文件的各个元素进行解析,读取元素信息后填充到 configuration 对象。在 XMLConfigBuilder 的mapperElement()方法中通过 XMLMapperBuilder 读取所有 mapper.xml 文件;见方法:org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XNode);见下图:
Mybatis源码解析(四)-配置加载初始化(建造者模式)_第10张图片
第三步: XMLMapperBuilder 的核心方法为 configurationElement(XNode),该方法对
mapper.xml 配置文件的各个元素进行解析,读取元素信息后填充到 configuration 对象。如下图所示:
Mybatis源码解析(四)-配置加载初始化(建造者模式)_第11张图片
从上面的源码我们可以知道,在 XMLMapperBuilder 解析过程中,有四个点需要注意:

  1. resultMapElements(List)方法用于解析 resultMap 节点;解析完之后数据保存在 configuration 对象的 resultMaps 属性中;
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第12张图片
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第13张图片
    和sql的对应关系如图:
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第14张图片
  2. XMLMapperBuilder 中在实例化二级缓存(见 cacheElement(XNode))、实例化 resultMap(见 resultMapElements(List))过程中都使用了***建造者模式***,而且是建造者模式的典型应用;
    2.1 resultMapElements(List)-》建造者模式
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第15张图片
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第16张图片
    这里看一下ResultMapping.Builder内部实现:首先由多种构造函数,和多个成员属性
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第17张图片
    然后可以看到每次设置成员属性后都会返回当前对象this,便于建造者模式的链式编程,也可以根据顺序进行设置成员属性:
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第18张图片
    然后我们可以看到具体的build过程是非常复杂的,这种场景使用建造者模式就是非常合适的:
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第19张图片
    2.2 cacheElement(XNode)-》建造者模式
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第20张图片
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第21张图片
    CacheBuilder内部实现:成员变量设置并返回当前对象this
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第22张图片
    复杂的构造过程
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第23张图片
  3. XMLMapperBuilder 和 XMLMapperStatmentBuilder 有 自 己 的 “ 秘 书 ”
    MapperBuilderAssistant。XMLMapperBuilder 和 XMLMapperStatmentBuilder 负责解析
    读取配置文件里面的信息,MapperBuilderAssistant 负责将信息填充到 configuration。
    将文件解析和数据的填充的工作分离在不同的类中,符合单一职责原则。在上面的源码1中分析中我们了解了XMLMapperBuilder 和 XMLMapperStatmentBuilder解析配置文件的过程, 2中也 讲解建造者模式的实现里面也可以看到MapperBuilderAssistant 将信息填充到configuration的过程:
  4. 在 buildStatementFromContext(List)方法中,创建 XMLStatmentBuilder 解析
    Mapper.xml 中 select、insert、update、delete 节点:
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第24张图片
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第25张图片
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第26张图片
    第四步: 在 XMLStatmentBuilder 的 parseStatementNode()方法中,对 Mapper.xml 中 select、insert、update、delete 节点进行解析,并调用 MapperBuilderAssistant 负责将信息填充到configuration。在理解 parseStatementNod()方法之前,有必要了解 MappedStatement,这个类 用 于 封 装 select 、 insert 、 update 、 delete 节 点 的 信 息 ;这个类同样是使用建造者模式 如 下 图 所 示 ,这里就不具体介绍了,和上面的建造者模式基本类似,不同的就是建造的具体内容不一样:
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第27张图片
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第28张图片
    通过上面的源码,我们可以了解到MappedStatement实现原理和sql关系如图:
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第29张图片
    至此,整个mybatis的配置文件解析过程基本完成,这里面我们可以看到所有配置文件解析的结果最后都是注册到configuration对象中,我们这里总结一下configuration对象的一些关系:
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第30张图片
    最后我们画一个整个解析的时序图,方便理解整个过程:
    Mybatis源码解析(四)-配置加载初始化(建造者模式)_第31张图片
    我们知道解析过程实际上是mybatis过程的第一步,解析完成后,当我们的应用程序进行sql操作的时候,具体是怎么通过mybatis操作数据库的内容,这部分将在后面介绍,敬请期待!!!!!

你可能感兴趣的:(Mybatis源码解析(四)-配置加载初始化(建造者模式))