【Mybatis】Mybatis学习由浅入深(三)

  哈喽大家好,今天是我来简书的第9天,分享一篇自己的技术博客,以后也会不定时的在简书分享Java学习笔记。也欢迎大家关注我的CSDN博客泪梦殇雨的博客_CSDN博客-二叉树,线上问题,图解Java领域博主

前言

  上一文提到了Mybatis的工作流程,这里回顾一下,然后这里主要讲第一步,加载配置信息初始化。

image.png

Mybatis在启动的时候都干了什么?🤔

  还是用上次的这个实现代码示例来开展吧。

  第一步就是“获取配置文件”,但是我们启动仅仅就获取下配置文件吗?当然不是,我们肯定是要解析配置文件,并将解析到的数据存起来供后面使用吧,这个是在哪里完成的呢?又是存在哪里呢?别着急这些问题后面解答。

  继续看下一行,使用Buider对象创建了一个SqlSessionFactory工厂对象,然后用这个创建了SqlSession才最终做到了和数据库的查询。啊?为啥要用Builder来创建啊,我直接new 一个不香吗?后面说后面说别急

image.png

  很明显SqlSession是完成和数据库交互的主力,而这个SqlSession怎么来的呢,是由SqlSessionFactory这个工厂创建的,给大家贴一下,基本全是返回SqlSession的,最后一个这里不提。可以看到这个接口的实现类有两个,不过直接获取,通过一个Buider对象创建的 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);

image.png

配置文件在哪完成解析存起来的?🤔

  • 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源码📖

image.png

  通过XMLConfigBuilder源码我们可以看到👇

  • 生成了一个xml解析器。
  • 初始化了一个Configuration对象。
  • 设置对应的properites属性。
  • 初始化是否解析的标志。
  • 初始化环境标识

  这是new XMLConfigBuilder完成的内容,这也只是完成解析的前置操作啊,解析,我要的解析在哪呢?别急马上就来,new XMLConfigBuilder之后不是还调用了parse方法吗?

image.png
image.png

  在这个parse中

  • 判定是否初始化一次
  • 完成对properties、settings等的解析处理工作

问题小结🔚

  mybatis在使用SqlSessionFactoryBuilder创建工厂对象的时候,借助XmlConfigBuider完成了对配置文件的解析工作和创建工厂对象工作。


Mybatis加载的内容存在哪个Java对象中?🤔

  上面的源码其实可以看出来,我们不是通过XmlConfigBuilder调用parse返回Configuration对象吗,然后用这个对象创建了DefaultSqlSessionFactory对象。那肯定是存在Configuration对象里咯😊

源码证实

  上面的源码跟到parse下面的parseConfiguration方法,看到里面针对很多标签的操作,那么接着找


image.png

  可以看到,解析完成后的数据,最终都set进Configuration对象里了,说明我们的猜测是对的。


SqlSessionFactory为什么是用Builder创建的?🤔

  在这里其实用到了工厂模式、建造者模式。建造者模式啪啪啪一顿操作,就搞出来了一个工厂对象,我只要用对象就好,其实我不关心咋创建出来的。这说明了解除了我和工具的耦合,我只要用就好了,我不需要创建。你那些复杂的逻辑自己管理。

Statement体现在哪呢?🤔

  差点漏了,开头说了加载了Statement对象,这里说明一下,首先可以确认的是肯定存在了Configuration里面,那还是在XmlConfigBuilder里找

源码说明🔭

image.png

  解析mappers时候,可以看到最终都调用了XMLMapperBuilder的parse方法,

  • 在这个parse方法里调用了configurationElement方法
  • 然后在configurationElement里创建了XMLStatementBuilder,这个初始化XMLStatementBuilder创建了MapperBuilderAssistant对象
  • 然后在configurationElement里调用了XMLStatementBuilder的parseStatementNode方法
  • 在parseStatementNode里调用了MapperBuilderAssistant的addMappedStatement方法
  • 在addMappedStatement方法的最后可以看到,创建了MappedStatement对象放进Configuration对象里

总结🔚

  Mybatis在启动时候加载全局配置文件和映射文件并将数据存储在Configuration对象里,然后创建一个SqlSessionFactory工厂对象,下面画张图示意下SqlSessionFactory的创建。

image.png
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容