zoukankan      html  css  js  c++  java
  • Mybatis源码解析3——核心类SqlSessionFactory,看完我悟了

    这是昨晚的武汉,晚上九点钟拍的,疫情又一次来袭,曾经熙熙攘攘的夜市也变得冷冷清清,但比前几周要好很多了。希望大家都能保护好自己,保护好身边的人,生活不可能像你想象的那么好,但也不会像你想象的那么糟。

    好了,言归正传,搞技术的努力提升技术才是王道。

    这是Mybatis 源码解析第三篇文章

    ①、Mybatis 源码解析1——从JDBC到Mybatis

    ②、Mybatis 源码解析2——从0到1实例搭建

    在上一篇文章《Mybatis从0到1实例搭建》中,可乐给大家手撸了一遍如何通过 Mybatis 对数据库一张表进行增删改查。至此,Mybatis 的前奏已经演奏完毕,接下来,我们将会进入高潮部分,请大家搬好小板凳,可乐将会用最通俗易懂,图文并茂的方式,给大家深入剖析 Mybatis 的实现原理。

    本篇文章我们首先解析 SqlSessionFactory 的创建过程。

    1、实例代码

    在实例代码中,我们在测试类中写了一个 init() 方法,里面包括了 SqlSessionFactory 的构建,分为两步。

    第一步:读取配置文件 mybatis-config.xml 输入流

    第二步:根据输入流构建 SqlSessionFactory;

    public void init() {
        //定义mybatis全局配置文件
        String resource = "mybatis-config.xml";
        //加载 mybatis 全局配置文件
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //构建sqlSession的工厂
        sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
    }
    
    

    没什么难的,去掉 try-catch,也就两行代码。

    InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
    

    是的,那只是你以为的两行代码,其实......

    话不多说,可乐就来给大家揭秘这冰山下面的东西。

    2、构建过程图示

    大家可以先看可乐为大家总结的两张流程图。

    温馨提示:结合流程图,再来服用代码,效果更佳。

    3、代码剖析

    根据上面的时序图,我们分析根据源码分析每个步骤。

    ①、获取配置文件输入流

    InputStream inputStream = Resources.getResourceAsStream("mybatis.config.xml");
    
    

    这里没什么好说的,就是获取配置文件的输入流。

    ②、build(in)

    这里的 in 就是上一步获取的输入流 inputStream。

      public SqlSessionFactory build(InputStream inputStream) {
        return build(inputStream, null, null);
      }
    
    

    在进入到 build 方法:

      public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
        try {
          XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
          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.
          }
        }
      }
    
    

    ③、XMLConfigBuilder(in)

    这一段代码是为了解析我们的配置文件,配置文件是 XML形式 ,我在之前的博客介绍过解析 XML 的几种方式。

    一种是基于树的结构来解析的称为DOM;另一种是基于事件流的形式称为SAX和(StAX)

    两者各有优缺点,我这里不做详细说明,想了解的可以看我之前的文章。

    而 Mybatis 使用的是 DOM 形式,并结合 XPath 来解析配置文件。

    ④、parse()

        public Configuration parse() {
            if (this.parsed) {
                throw new BuilderException("Each XMLConfigBuilder can only be used once.");
            } else {
                this.parsed = true;
                this.parseConfiguration(this.parser.evalNode("/configuration"));
                return this.configuration;
            }
        }
    
    

    从 /configuration 标签处开始解析。然后我们进入到 this.parseConfiguration() 方法中:

        private void parseConfiguration(XNode root) {
            try {
                this.propertiesElement(root.evalNode("properties"));
                Properties settings = this.settingsAsProperties(root.evalNode("settings"));
                this.loadCustomVfs(settings);
                this.loadCustomLogImpl(settings);
                this.typeAliasesElement(root.evalNode("typeAliases"));
                this.pluginElement(root.evalNode("plugins"));
                this.objectFactoryElement(root.evalNode("objectFactory"));
                this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
                this.reflectorFactoryElement(root.evalNode("reflectorFactory"));
                this.settingsElement(settings);
                this.environmentsElement(root.evalNode("environments"));
                this.databaseIdProviderElement(root.evalNode("databaseIdProvider"));
                this.typeHandlerElement(root.evalNode("typeHandlers"));
                this.mapperElement(root.evalNode("mappers"));
            } catch (Exception var3) {
                throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3);
            }
        }
    
    

    看到这是不是很熟悉了,这不就是mybatis-config.xml 配置文件里面的各个标签名嘛,是的,这就是解析该文件,然后全部放在 configuration 对象中。需要注意的是,这里的 configuration 对象不仅包括 mybatis-config.xml 文件内容,也包括 xxxMapper.xml 文件内容。

    ⑤、build(configuration)

      public SqlSessionFactory build(Configuration config) {
        return new DefaultSqlSessionFactory(config);
      }
    
    
    

    就是去 new 了一个 DefaultSqlSessionFactory 对象,将 configuration 作为参数。

    ⑥、DefaultSqlSessionFactory(configuration)

        public DefaultSqlSessionFactory(Configuration configuration) {
            this.configuration = configuration;
        }
    
    

    4、总结

    自此,SqlSessionFactory 的创建过程就讲完了,总的来说就是一个封装了配置文件的工厂类。那么得到了 SqlSessionFactory 这个工厂对象,接下来干嘛?生产 SqlSession,然后通过 SqlSession 进行数据库的增删改查操作

    没错,接下来,可乐将给大家介绍 SqlSession 的交互过程,这也是 Mybatis 里面最重要的一个对象。

    作者:IT可乐

    资源:微信搜【IT可乐】关注我,回复 【电子书】有我特别筛选的免费电子书。
    本文版权归作者所有,欢迎转载,但未经作者同意不能转载,否则保留追究法律责任的权利。
  • 相关阅读:
    INT 3 中断调试处理流程
    调试事件的处理结束
    [IDA] 自动下载符号
    06 内存断点
    05 软件断点
    C#2.0新增功能02 泛型
    C#2.0新增功能01 分部类与分部方法
    xBIM 实战04 在WinForm窗体中实现IFC模型的加载与浏览
    xBIM 实战03 使用WPF技术实现IFC模型的加载与浏览
    xBIM 实战02 在浏览器中加载IFC模型文件并设置特效
  • 原文地址:https://www.cnblogs.com/ysocean/p/15217160.html
Copyright © 2011-2022 走看看