深入理解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的初始化就是上述过程。

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