MyBatis源码剖析(2)SqlSessionFactoryBuilder

455 阅读3分钟

接下来的几篇文章,将会围绕配置文件的解析进行,这篇文章重点讲述SqlSessionFactoryBuilder

SqlSessionFactoryBuilder的作用

回顾一下MyBatis的测试启动类。

public static void main(String[] args) throws IOException {
    Reader reader = Resources.getResourceAsReader("mybatis_config.xml");
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);

    SqlSession sqlSession = sqlSessionFactory.openSession();

    List<Person> persons = sqlSession.selectList("com.lightingsui.mapper.IPersonMapper.selectAll");    

    persons.forEach(System.out::println);
}

作用:SqlSessionFactoryBuilder主要就是构建SqlSessionFactory,即SqlSession的工厂,内部会把上一步的流解析成Configuration,然后根据Configuration构建SqlSessionFactory。

解析流程

SqlSessionFactoryBuilder内部并没有构造函数,而是通过build方法进行处理,内部存在多个重载的build方法。

build()方法

build方法内部其实算作两个流派,一个是Reader流派,另一个为InputStream流派,本质上的区别就是构建XMLConfigBuilder的方式不同。下面就以Reader流派的方式举例。

  public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
    try {
      // 构建XML解析器
      XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);

      // 调用另一个重载的build方法
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      // 错误日志处理
      ErrorContext.instance().reset();
      try {
        reader.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }

方法共有3个参数:

  • reader
  • 配置文件到的传输流
  • environment
  • properties

environment

environment的作用与在xml中配置environments的default属性是一致的。作用就是选择一个默认的连接。

<!-- 设置一个默认的连接环境信息 -->
<environments default="mysql_developer">
    <!-- 连接环境信息,取一个任意唯一的名字 -->
    <environment id="mysql_developer">
        <!-- mybatis使用jdbc事务管理方式 -->
        <transactionManager type="jdbc"/>
        <!-- mybatis使用连接池方式来获取连接 -->
        <dataSource type="pooled">
            <!-- 配置与数据库交互的4个必要属性 -->
            <property name="driver" value="${mysql.driver}"/>
            <property name="url" value="${mysql.url}"/>
            <property name="username" value="${mysql.username}"/>
            <property name="password" value="${mysql.password}"/>
        </dataSource>
    </environment>
</environments>

存在一个问题,如果在xml配置了,但是通过代码指定了environment,那么将使用哪个呢,其实透过XmlConfigBuilder源代码就可以知道(在后面的文章中),会优先使用通过代码指定的environment。

properties

properties的作用和在xml中指定的properties的作用是一致的。加载一些数据库的连接信息。

<!-- 加载类路径下的属性文件 -->
<properties resource="db.properties"/>

那么就也存在上面environment的问题,优先使用xml还是代码的配置,结果为优先使用代码中指定的properties,将会在后面的XmlConfigBuilder源码解析的文章中进行深入了解。


在上面的build方法中,最后又调用了另一个被重载的build方法,而传递的参数为parser.parse(),此方法的返回值为Configuration对象,Configuration为MyBatis全程都存在的配置信息。

此重载的方法返回了一个DefaultSqlSessionFactory(会在后面的源码剖析文章中出现),即SqlSessionFactory默认的实现类,内部是通过Configuration构架出来的。

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