前言
上一文提到了Mybatis的工作流程,这里回顾一下,然后这里主要讲第一步,加载配置信息初始化。
Mybatis在启动的时候都干了什么?🤔
还是用上次的这个实现代码示例来开展吧。
第一步就是“获取配置文件”,但是我们启动仅仅就获取下配置文件吗?当然不是,我们肯定是要解析配置文件,并将解析到的数据存起来供后面使用吧,这个是在哪里完成的呢?又是存在哪里呢?别着急这些问题后面解答。
继续看下一行,使用Buider对象创建了一个SqlSessionFactory工厂对象,然后用这个创建了SqlSession才最终做到了和数据库的查询。啊?为啥要用Builder来创建啊,我直接new 一个不香吗?后面说后面说别急
很明显SqlSession是完成和数据库交互的主力,而这个SqlSession怎么来的呢,是由SqlSessionFactory这个工厂创建的,给大家贴一下,基本全是返回SqlSession的,最后一个这里不提。可以看到这个接口的实现类有两个,不过直接获取,通过一个Buider对象创建的 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
配置文件在哪完成解析存起来的?🤔
- new SqlSessionFactoryBuilder().build(in);创建工厂对象的时候完成的
- 工厂对象的作用就是创建SqlSession,它不需要重复创建是一个单例对象
- 我们的配置文件不管是全局配置文件还是映射文件,也都只需要加载一次就可以了
- 这个SqlSessionFactoryBuilder就是用建造者模式完成这两个步骤,加载配置文件和创建工厂对象
源码证实🔭:
SqlSessionFactoryBuilder源码📖
public SqlSessionFactory build(InputStream inputStream) {
return build(inputStream, null, null);
}
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
// 用于解析 mybatis-config.xml
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
// 解析XML,最终返回一个 DefaultSqlSessionFactory
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
通过SqlSessionFactoryBuilder源码我们可以看到👇
- 通过XMLConfigBuilder加载
Resources.getResourceAsStream("mybatis-config.xml")
加载得到的字节流。 - XMLConfigBuilder初始化完成之后调用了parse方法得到了Configuration对象
- 最终创建了一个DefaultSqlSessionFactory工厂对象返回
XMLConfigBuilder源码📖
通过XMLConfigBuilder源码我们可以看到👇
- 生成了一个xml解析器。
- 初始化了一个Configuration对象。
- 设置对应的properites属性。
- 初始化是否解析的标志。
- 初始化环境标识
这是new XMLConfigBuilder完成的内容,这也只是完成解析的前置操作啊,解析,我要的解析在哪呢?别急马上就来,new XMLConfigBuilder之后不是还调用了parse方法吗?
在这个parse中
- 判定是否初始化一次
- 完成对properties、settings等的解析处理工作
问题小结🔚
mybatis在使用SqlSessionFactoryBuilder创建工厂对象的时候,借助XmlConfigBuider完成了对配置文件的解析工作和创建工厂对象工作。
Mybatis加载的内容存在哪个Java对象中?🤔
上面的源码其实可以看出来,我们不是通过XmlConfigBuilder调用parse返回Configuration对象吗,然后用这个对象创建了DefaultSqlSessionFactory对象。那肯定是存在Configuration对象里咯😊
源码证实
上面的源码跟到parse下面的parseConfiguration方法,看到里面针对很多标签的操作,那么接着找
可以看到,解析完成后的数据,最终都set进Configuration对象里了,说明我们的猜测是对的。
SqlSessionFactory为什么是用Builder创建的?🤔
在这里其实用到了工厂模式、建造者模式。建造者模式啪啪啪一顿操作,就搞出来了一个工厂对象,我只要用对象就好,其实我不关心咋创建出来的。这说明了解除了我和工具的耦合,我只要用就好了,我不需要创建。你那些复杂的逻辑自己管理。
Statement体现在哪呢?🤔
差点漏了,开头说了加载了Statement对象,这里说明一下,首先可以确认的是肯定存在了Configuration里面,那还是在XmlConfigBuilder里找
源码说明🔭
解析mappers时候,可以看到最终都调用了XMLMapperBuilder的parse方法,
- 在这个parse方法里调用了configurationElement方法
- 然后在configurationElement里创建了XMLStatementBuilder,这个初始化XMLStatementBuilder创建了MapperBuilderAssistant对象
- 然后在configurationElement里调用了XMLStatementBuilder的parseStatementNode方法
- 在parseStatementNode里调用了MapperBuilderAssistant的addMappedStatement方法
- 在addMappedStatement方法的最后可以看到,创建了MappedStatement对象放进Configuration对象里
总结🔚
Mybatis在启动时候加载全局配置文件和映射文件并将数据存储在Configuration对象里,然后创建一个SqlSessionFactory工厂对象,下面画张图示意下SqlSessionFactory的创建。