01 Mybatis源码篇---创建SqlSessionFactory对象

本文介绍MyBatis中SqlSessionFactory的创建过程,包括SqlSessionFactoryBuilder的作用、XMLConfigBuilder的配置解析及Configuration对象的构建。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     在“Mybatis入门”篇中,以一个简单的demo,让我们初步了解MyBatis的运行机制。
     官方解释"每个基于MyBatis的应用都是以一个SqlSessionFactory的实例为中心,SqlSessionFactory的实例可以通过SqlSessionFactoryBuilder获得。而SqlSessionFactoryBuilder则可以从XML配置文件或一个预先定制的configuration的实例构建SqlSessionFactory的实例"
     下面跟踪源码查看构建SqlSessionFactory实例的过程。
1、创建SqlSessionFactory对象:

/**
 * 获取 SqlSessionFactory
 * Mybatis 通过SqlSessionFactory获取SqlSession, 然后才能通过SqlSession与数据库进行交互
 * @return
 */
private SqlSessionFactory getSqlSessionFactory(){
    /**
     * MyBatis的配置文件
     */
    String resource = "mybatis-config.xml";
    SqlSessionFactory sqlSessionFactory = null;
    InputStream stream =  null;
    try {
        /**
         * 将Mybatis配置文件转成InputStream字节流,或者转成Reader字符流,两种方式MyBatis都支持
         */
        stream = Resources.getResourceAsStream(resource);
        /**
         * 根据SqlSessionFactoryBuilder()创建SqlSessionFactory
         */
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(stream);
    }catch (Exception e){
        e.printStackTrace();
    }
    return  sqlSessionFactory;
}

2、首先我们看一下SqlSessionFactoryBuilder()是如何构建SqlSessionFactory对象的。

public class SqlSessionFactoryBuilder {

  public SqlSessionFactory build(Reader reader) {
    return build(reader, null, null);
  }

  public SqlSessionFactory build(Reader readerString environment) {
    return build(readerenvironment, null);
  }

  public SqlSessionFactory build(Reader readerProperties properties) {
    return build(reader, null, properties);
  }

  public SqlSessionFactory build(Reader readerString environmentProperties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(readerenvironmentproperties);
      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.
      }
    }
  }

  /**
   *
   * @param inputStream 将MyBatis的配置文件流传入构造方法中
   * @return
   */
  public SqlSessionFactory build(InputStream inputStream) {
    return build(inputStream, null, null);
  }

  /**
   *
   * @param inputStream 将MyBatis的配置文件流传入构造方法中
   * @param environment 环境
   * @return
   */
  public SqlSessionFactory build(InputStream inputStreamString environment) {
    return build(inputStreamenvironment, null);
  }

  /**
   *
   * @param inputStream 将MyBatis的配置文件流传入构造方法中
   * @param properties  properties属性设置
   * @return
   */
  public SqlSessionFactory build(InputStream inputStreamProperties properties) {
    return build(inputStream, null, properties);
  }

  /**
   *
   * @param inputStream MyBatis配置文件字节流
   * @param environment MyBatis 可以配置环境 如果忽略了环境参数,那么默认环境将会被加载。后面我们会详细讲到
   * @param properties  properties设置,从此处可以看出,mybatis配置文件中可以不配置properties。这也是我前面所说的第三种配置properties的方式,优先级最高
   * @return
   */
  public SqlSessionFactory build(InputStream inputStreamString environmentProperties properties) {
    try {
      /**
       *使用XMLConfigBuilder解析字节流,创建XMLConfigBuilder对象
       */
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStreamenvironmentproperties);
      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.
      }
    }
  }

  /**
   * 创建SqlSessionFactory 对象
    * @param config XMLConfigBuilder对象
   * @return
   */
  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }

}

SqlSessionFactoryBuilder对象创建SqlSessionFactory,我主要解释一下字节流,字符流可参考字节流。

3、创建SqlSessionFactory 对象,主要是通过XMLConfigBuilder对象来解析MyBatis配置文件,下面我们了解一下解析过程。
XMLConfigBuilder类源码:


/**
 * 解析XML配置文件
 * @param inputStream
 @param environment
 @param props
 */
public XMLConfigBuilder(InputStream inputStreamString environmentProperties props) {
  this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver())environmentprops);
}

private XMLConfigBuilder(XPathParser parserString environmentProperties props) {
  /**
   * super(new Configuration());
   this.configuration = configuration;
   this.typeAliasRegistry = this.configuration.getTypeAliasRegistry();   配置MyBatis的内建别名
   this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry(); 配置MyBatis默认的类型处理器 后面详细解释
   */
  super(new Configuration());
  ErrorContext.instance().resource("SQL Mapper Configuration");
  this.configuration.setVariables(props);
  this.parsed false;
  this.environment = environment;
  this.parser = parser;
}

/**
 * 在SqlSessionFactoryBuilder对象中创建完成XMLConfigBuilder对象时,调用此方法 return build(parser.parse());
 * @return
 */
public Configuration parse() {
  if (parsed) {
    throw new BuilderException("Each XMLConfigBuilder can only be used once.");
  }
  parsed true;
  parseConfiguration(parser.evalNode("/configuration"));
  return configuration;
}

/**
 * 此方法就是解析MyBatis配置文件configuration节点及子节点
 * 这里表明configuration节点下面,可以配置如下节点
 * @param root
 */
private void parseConfiguration(XNode root) {
  try {
    //issue #117 read properties first
    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"));
    settingsElement(settings);
    environmentsElement(root.evalNode("environments"));
    databaseIdProviderElement(root.evalNode("databaseIdProvider"));
    typeHandlerElement(root.evalNode("typeHandlers"));
    mapperElement(root.evalNode("mappers"));
 catch (Exception e) {
    throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + ee);
  }
}

4、通过上面的XMLConfigBuilder 类,构建Configuration对象,最后DefaultSqlSessionFactory(config)创建SqlSessionFactory对象。

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

     对于如何创建SqlSessionFactory对象,源码到此结束。
     本人初入行不久,望大神们不吝赐教。

















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值