天天看點

01 Mybatis源碼篇---建立SqlSessionFactory對象

     在“Mybatis入門”篇中,以一個簡單的demo,讓我們初步了解MyBatis的運作機制。      官方解釋"每個基于MyBatis的應用都是以一個SqlSessionFactory的執行個體為中心,SqlSessionFactory的執行個體可以通過SqlSessionFactoryBuilder獲得。而SqlSessionFactoryBuilder則可以從XML配置檔案或一個預先定制的configuration的執行個體建構SqlSessionFactory的執行個體"      下面跟蹤源碼檢視建構SqlSessionFactory執行個體的過程。 1、建立SqlSessionFactory對象:

private SqlSessionFactory  getSqlSessionFactory(){

    String resource =  "mybatis-config.xml" ;

    SqlSessionFactory sqlSessionFactory =  null;

    InputStream stream =  null;

    try {

        stream = Resources. getResourceAsStream(resource) ;

        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.

      }

    }

  }

  public SqlSessionFactory  build(InputStream inputStream) {

    return build(inputStream , null, null) ;

  }

  public SqlSessionFactory  build(InputStream inputStream , String environment) {

    return build(inputStream , environment , null) ;

  }

  public SqlSessionFactory  build(InputStream inputStream , Properties properties) {

    return build(inputStream , null, properties) ;

  }

  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.

      }

    }

  }

  public SqlSessionFactory  build(Configuration config) {

    return new DefaultSqlSessionFactory(config) ;

  }

}

SqlSessionFactoryBuilder對象建立SqlSessionFactory,我主要解釋一下位元組流,字元流可參考位元組流。

3、建立SqlSessionFactory 對象,主要是通過XMLConfigBuilder對象來解析MyBatis配置檔案,下面我們了解一下解析過程。 XMLConfigBuilder類源碼:

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()) ;

  ErrorContext. instance().resource( "SQL Mapper Configuration") ;

  this. configuration.setVariables(props) ;

  this. parsed =  false;

  this. environment = environment ;

  this. parser = parser ;

}

public Configuration  parse() {

  if ( parsed) {

    throw new BuilderException( "Each XMLConfigBuilder can only be used once.") ;

  }

  parsed =  true;

  parseConfiguration( parser.evalNode( "/configuration")) ;

  return  configuration ;

}

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對象,源碼到此結束。      本人初入行不久,望大神們不吝賜教。

繼續閱讀