MyBatis运行原理(一)SqlSessionFactory对象创建过程分析

一、写在前面

MyBatis基于接口形式的编程主要步骤:

1.创建SqlSessionFactory对象。

2.根据SqlSessionFactory对象获取SqlSession对象。

3.为mapper 接口创建代理对象。

4.使用mapper 接口代理对象执行对应的增删改查操作。

下面就通过分析源码来探索在创建SqlSessionFactory对象的过程中都发生了什么。

二、SqlSessionFactory对象创建过程分析

入口程序:

    private SqlSessionFactory getSqlSessionFactory() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream is = Resources.getResourceAsStream(resource);
        // 将断点打在下面的代码前
        return new SqlSessionFactoryBuilder().build(is);
    }

1.首先会跳到SqlSessionFactoryBuilder类中的build(InputStream inputStream)方法。

  // ======= SqlSessionFactoryBuilder 类中的方法 =======
  public SqlSessionFactory build(InputStream inputStream) {
    return build(inputStream, null, null);
  }

在该方法中调用了另一个build(InputStream inputStream, String environment, Properties properties)方法,定义了一个XMLConfigBuilder对象,通过这个对象调用自身的parse()方法对配置文件进行解析。

  // ======= SqlSessionFactoryBuilder 类中的方法 =======
  public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      // 创建一个XMLConfigBuilder 解析器
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      // 调用parser 解析器中的parse()方法
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        inputStream.close();
      } catch (IOException e) {
      }
    }
  }

2.下面来看看是如何进行文件解析的,跳到XMLConfigBuilder类中的parse()方法,在parse()方法中调用了parseConfiguration(XNode root)方法,这个方法用于解析配置文件。

  // ======= XMLConfigBuilder类中的方法 =======

  public Configuration parse() {
    if (parsed) {
      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    parsed = true;
    /** 
     * parseConfiguration() 方法用于解析MyBatis 全局配置文件与SQL 映射文件中的相关配置
     * "/configuration" 就是对应全局配置文件中的 标签
     * parser 是XPathParser 类的实例,通过该对象解析XML 配置文件
     */
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
  }

下面是parseConfiguration(XNode root)中的具体源码,在这个方法中会对MyBatis 全局配置文件中的信息与SQL 映射文件中的信息进行解析,并把对应的信息保存在Configuration对象中。建议具体了解一下其中的settingsElement(settings);方法与mapperElement(root.evalNode("mappers"));方法。

  // ======= XMLConfigBuilder类中的方法 =======

  private void parseConfiguration(XNode root) {
    try {
      /** 
      * settings、typeAliases、plugins 等用于对应MyBatis 全局配置文件中的标签
      * 将MyBatis 全局配置文件的标签信息保存在Configuration 对象中
      */
      propertiesElement(root.evalNode("properties"));
      Properties settings = settingsAsProperties(root.evalNode("settings"));
      loadCustomVfs(settings);
      typeAliasesElement(root.evalNode("typeAliases"));
      pluginElement(root.evalNode("plugins"));
      objectFactoryElement(root.evalNode("objectFactory"));
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      reflectorFactoryElement(root.evalNode("reflectorFactory"));
      // 将 标签中的设置也保存在Configuration 中
      settingsElement(settings);
      // 设置事务的相关配置与数据源
      environmentsElement(root.evalNode("environments"));
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      typeHandlerElement(root.evalNode("typeHandlers"));
      /**
       * 接着开始解析标签中的信息
       * 在mapperElement() 方法中会对 标签下的子标签 进行解析,
       * 解析完 标签后,接着调用XMLMapperBuilder 中的方法对SQL 映射文件进行解析,
       * 并把相应的信息也保存在Configuration 对象中
       */
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }

通过上面对parseConfiguration(XNode root)方法的分析,我们知道MyBatis 全局配置文件与SQL 映射文件中的信息都会保存在Configuration 对象中。这其中还涉及到了很多的方法,在这里就不一一讲述了,大家可以自己进行查看。

3.将信息保存在Configuration对象中后通过XMLConfigBuilder类中的parse()方法返回,作为参数传递到SqlSessionFactory类中的build(Configuration config)方法。

最后接着返回一个DefaultSqlSessionFactory对象。到这里SqlSessionFactory对象就完成了创建的全部过程。

// ======= SqlSessionFactoryBuilder 类中的方法 =======

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

调用过程时序图:
MyBatis运行原理(一)SqlSessionFactory对象创建过程分析_第1张图片

三、总结

SqlSessionFactory对象创建的过程中,对MyBatis 全局配置文件与SQL 映射文件中的信息进行了解析与保存,为后续创建会话(SqlSession)提供了基础。这篇博文只是把创建过程进行了分析,略过了其中的一些细节,如果大家感兴趣可以自己参考源码。

你可能感兴趣的:(MyBatis源码分析,MyBatis运行原理,MyBatis)