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

     在“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 reader String environment) {
    return build(reader environment , null) ;
  }

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

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

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

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

  /**
   * 创建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 inputStream String environment Properties props) {
  this( new XPathParser(inputStream , true, props , new XMLMapperEntityResolver()) environment props) ;
}

private  XMLConfigBuilder(XPathParser parser String environment Properties 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: " + e e) ;
  }
}

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

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

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

















你可能感兴趣的:(Mybatis,mybatis,mybatis源码)