深入理解MyBatis——初始化

我們知道使用MyBatis前是需要初始化的,我們來看一段代碼:

String resource = "mybatis.xml";  
InputStream inputStream = Resources.getResourceAsStream(resource);  
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);  
SqlSession sqlSession = sqlSessionFactory.openSession();  
List list = sqlSession.selectList("edu.zhwei.mapper.sqlId");  

上述代碼所經歷的階段:
1.讀取配置文件並創建SqlSessionFactory
2.獲得sqlSession
3.執行查詢

而MyBatis的初始化就在階段1中,更準確的說是在第三行代碼,根據配置文件,創建立SqlSessionFactory對象。那就讓我們看一看這一行代碼究竟發生了什麼。

SqlSessionFactoryBuilder

相關源碼:

 public SqlSessionFactory build(InputStream inputStream) {
    return build(inputStream, null, null);
  }

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
    //創建XMLConfigBuilder對象,
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      //parser.parse()方法返回一個Configuration 對象,這裏需要說明一下。
      //返回SqlSessionFactory
      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) {
//根據Configuration對象,返回DefaultSqlSessionFactory
    return new DefaultSqlSessionFactory(config);
  }

說明:根據傳入的inputStream, environment, properties創建XMLConfigBuilder對象,XMLConfigBuilder.parse()用來將inputStream創建成一個Configuration對象,然後在調用build(Configuration config)方法返回DefaultSqlSessionFactory。

那麼parse()方法是如何實現的呢?

XMLConfigBuilder類

parse()方法源碼:

public Configuration parse() {
    if (parsed) {
      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    parsed = true;
    //parser.evalNode("/configuration")返回一個XNode 對象
   //parseConfiguration(XNode)將配置文件中配置的信息解析並設置到Configuration對象中
   parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
  }

  private void parseConfiguration(XNode root) {
    try {
//解析各種類型的節點,如properties、typeAliases、plugins等
      propertiesElement(root.evalNode("properties")); //issue #117 read properties first
      typeAliasesElement(root.evalNode("typeAliases"));
      pluginElement(root.evalNode("plugins"));
      objectFactoryElement(root.evalNode("objectFactory"));
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      settingsElement(root.evalNode("settings"));
      environmentsElement(root.evalNode("environments")); // read it after objectFactory and objectWrapperFactory issue #631
      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);
    }
  }

說明:parser.evalNode(“/configuration”)返回一個XNode 對象,我們看一下evalNode方法,我們發現XNode是取自XPathParser的。

XPathParser.evalNode源碼:

public XNode evalNode(String expression) {
    return evalNode(document, expression);
  }

  public XNode evalNode(Object root, String expression) {
    Node node = (Node) evaluate(expression, root, XPathConstants.NODE);
    if (node == null) {
      return null;
    }
    return new XNode(this, node, variables);
  }

XPathParser類:

public class XPathParser {

 //document對象
  private Document document;
  private boolean validation;
  //entityResolver對象
  private EntityResolver entityResolver;
  private Properties variables;
  private XPath xpath;
 ........
}

我們需要關注一下document對象和entityResolver對象。
document對象:包含了XML配置信息
entityResolver:包含了XML中的DTD信息

因此,XMLConfigBuilder調用parse()方法:會從XPathParser中取出 configuration節點對應的XNode對象,然後解析此XNode節點的子,產生Configration對象。

至此,XMLConfigBuilder的parse()就分析完成了。

重新修改

我們再來看第三行代碼


//看這裏
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);  

//將第三行代碼改爲如下三行代碼

//第一步創建XMLConfigBuilder
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, null,null);  
//第二步:執行parse()得到代表配置文件的Configuration對象
Configuration config = parser.parse();  

//根據Configuration創建DefaultSqlSessionFactory2
SqlSessionFactory = new DefaultSqlSessionFactory(config);

MyBatis的初始化就是上述過程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章