mybatis源码解读------读取配置文件

背景

mybatis作为一个轻量级的ORM框架,凭借着动态SQL,嵌套结果等技术风靡一些公司,作为一个初级程序员,看一些优秀的框架代码对于个人编码能力的提升有着不错的效果,其中的技术选型,设计模式等也是值得学习的。

先来一段普通的mybatis的代码:

InputStream inputStream = Resources.getResourceAsStream("SqlMappingConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
SqlSession session = factory.openSession();
IUserDao userDao = session.getMapper(IUserDao.class);
List<User> users = userDao.findAll();
users.forEach(System.out::println);
session.close();
inputStream.close();

这篇文章着重分析这一片段

InputStream inputStream = Resources.getResourceAsStream("SqlMappingConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);

开始分析

1.读取文件流

先看Resource这个类
mybatis源码解读------读取配置文件_第1张图片
不难发现其中的成员变量并不多,但是却包含了多种读取文件的重载方法
mybatis源码解读------读取配置文件_第2张图片
我们先着重看着Resource.getResourceAsStream(String resource)这个方法,是通过读取预置的配置文件开始的

参数名
resource SqlMappingConfig.xml

mybatis源码解读------读取配置文件_第3张图片
跟进getResourceAsStream(ClassLoader classLoader,String resource)这个方法

参数名
loader null
resource SqlMappingConfig.xml

mybatis源码解读------读取配置文件_第4张图片
发现调用了一个mybatis封装的类的方法,ClassLoaderWapper这个类,进入后观察其成员变量
mybatis源码解读------读取配置文件_第5张图片
其实就是内部封装了两个ClassLoader的实例,这个会在后面的方法被使用
其次便是getResourceAsStream(String resource,ClassLoader classloader)这个方法

参数名
classLoader null
resource SqlMappingConfig.xml

mybatis源码解读------读取配置文件_第6张图片
在阅读源码时,如果出现方法入参是一个方法的返回值时,优先查看这个getClassLoaders(ClassLoader classLoader)这个方法,这个方法提供了一个类加载器的使用顺序,由此可以看出systemClassLoader算是一个兜底的类加载器,自己传的类加载器则优先级最高(按照本文这种使用方法会传null,使用defaultClassLoader)

参数名
classLoader null

mybatis源码解读------读取配置文件_第7张图片
再继续查看getResourceAsStream(String resource,ClassLoader[] classloader)这个方法,这里才是真正调用ClassLoader读取文件流

参数名
resource SqlMappingConfig.xml
classLoader [null,object…](只要有一个不为null,后面的就没有意义了)

mybatis源码解读------读取配置文件_第8张图片
这里观察源代码发现mybatis会默认帮我们拼上"/",但是可以避免多读一次,可以自行把”/“加上
这个循环也验证里加载器的优先级
到这里,文件已经变成文件流了,数据也从外存中进入内存,可以进行文件流的操作了

领悟的小技巧
	1. 当出现需要多种策略且不确定哪种策略要使用时,可以使用数组设置对应的优先级,并指定一个兜底的
	策略
	2. 不难发现在源码中存在很多次重载,并且代码很短,便于阅读和修改

2.创建工厂并读取文件流并配置mybatis

首先是构建者模式(设计模式),SqlSessionFactoryBuilder这个类
mybatis源码解读------读取配置文件_第9张图片
同样提供多种构建SqlSessionFactory的方法,这里使用的是build(InputStrean in),往下看
mybatis源码解读------读取配置文件_第10张图片
XMLConfigBuilder同样使用了构建者模式,XMLConfigBuilder是对mybatis的配置文件进行解析的类,会对myabtis解析后的信息存放在Configuration对象中,Configuration对象会贯穿整个mybatis的执行流程,为mybatis的执行过程提供各种需要的配置信息
mybatis源码解读------读取配置文件_第11张图片
先看成员变量

变量名 作用
parsed 标记文件是否已经加载过了
parser 文件流转换对象
environment 环境(本文不做详细赘述)
localReflectFactory 缓存工厂(本文不做详细赘述)

构造方法的调用关系
mybatis源码解读------读取配置文件_第12张图片
这里面有两个类
XMLMapperEntityResover:配置文件处理类,里面包含配置文件dtd所在的位置
mybatis源码解读------读取配置文件_第13张图片
XPathParse:实际开始解析xml文件
同样大量重载的构造器,重点看这个
在这里插入图片描述
先对已有的变量赋值
commonConstructor(boolean validation, Properties variables, EntityResolver entityResolver)

变量名
validation true
variables null
entityResolver object(在XMLConfigBuilder构造器中new的对象)

mybatis源码解读------读取配置文件_第14张图片
创建文档流对象
createDocument(InputSource inputSource)

变量名
inputSource new InputSource(inputStream)

mybatis源码解读------读取配置文件_第15张图片
这是读取XML的主要方法,mybatis使用的是xerces技术,就现在来看,xml配置文件这样的形式已经是不怎么流行了,这里就不在赘述了,总之经过这个方法之后,我们将文件流变成了Document文档流对象
接下来就是解析文档流对象
mybatis源码解读------读取配置文件_第16张图片
这里对parsed这个标志位做了个判断,防止反复解析
接着进入parseConfiguration(XNode root)这个方法,根据文档创建mybatis的配置
mybatis源码解读------读取配置文件_第17张图片
这里关注一下Configuration这个类
mybatis源码解读------读取配置文件_第18张图片
发现有大量关于mybatis的配置抽象成员,在完成parseConfiguration这个方法后,也意味着配置工作将要接近尾声了,最后通过SQLSessionFactory的build(Configuration config)构建默认的工厂
mybatis源码解读------读取配置文件_第19张图片

领悟的小技巧
	1. 这里出现了大量了工厂来进行解耦,不难发现对于开发来说工厂模式是个不错的选择,
	2. 期间我们发现mybatis提供了大量的接口和默认实现,这是提升代码灵活性的一种方法

你可能感兴趣的:(java,开发语言,后端,mysql,mybatis)