createDocument函数, 其实就是通过 DOM 解析 XML 文件的过程中的几个步骤,获得document, 具体可以参见 「mybatis 解析配置文件(一)之XML的DOM解析方式」, 里面提到了 Java 中使用 DOM 解析 XML 的步骤, 大致如下:
创建 DocumentBuilderFactory 对象;
通过 DocumentBuilderFactory 创建DocumentBuilder对象;
通过DocumentBuilder, 从文件或流中创建通过Document对象;
创建XPathFactory对象, 并通过XPathFactory创建XPath对象;
通过XPath解析出XPathExpression对象;
使用XPathExpression在文档中搜索出相应的节点。
刚刚提到的两个函数, 已经完成了前4部分, 获得了Document对象, Xpath对象, 并返回后将其赋值给了相应的成员变量。
也就是说, 到了这一步, 我们已经获得了XpathParser对象, 该对象中已经含有 mybatis-config.xml 文件对应的 Document Object, 即document和xpath。 通过document和xpath,我们可以对 mybatis-config.xml 进行后两部操作操作。
后面几个步骤, 是在XMLConfiguration对象的parse()函数中使用到, 详情见 2.3.5。
2.3.4 new Configuration()之前提到过, 配置文件解析的本质就是获得Configuration对象。
现在, Configuration对象在解析的过程中第一次出现了。
那我们就可以返回这个对象了?
当然不是, 这个对象现在只是创建, 后续还有很多成员变量需要根据 XML 配置文件解析后来赋值。
2.3.5 parser.parse()这里的parser是XMLConfigBuilder对象。
public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; parseConfiguration(parser.evalNode("/configuration")); return configuration; }这个函数返回的Configuration对象就是最终写入SqlSessionFatory对应成员变量的对象。
由于配置文件解析的本质就是获得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); // read it after objectFactory and objectWrapperFactory issue #631 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); } }其对应的过程就是解析 XML 配置文件中 properties, settings, typeAliases, plugins, objectFactory, objectWrapperFactory, reflectorFactory, environments, databaseIdProvider, typeHandlers, mappers, 这些子节点。
其中的evalNode函数, 在其函数过程中, 会调用XParhParser中的函数, 对 xml 节点进行解析:
private Object evaluate(String expression, Object root, QName returnType) { try { return xpath.evaluate(expression, root, returnType); } catch (Exception e) { throw new BuilderException("Error evaluating XPath. Cause: " + e, e); } }以上过程就是我们 2.3.3 中提到的第 5, 6 步过程。
具体的在后续的文章中在深入了解。
2.3.6 build(configuration)该函数就是创建一个具体的SqlSessionFactory对象。
public SqlSessionFactory build(Configuration config) { return new DefaultSqlSessionFactory(config); } public DefaultSqlSessionFactory(Configuration configuration) { this.configuration = configuration; }就是创建DefaultSqlSessionFactory对象, 并将configuration赋值给相应的成员变量。
更具体的解析配置的过程, 后续分享。