上面,拿到了XML文件流,下面开始解析这个文件流。
解析的入口是
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
// 开始解析XML内容
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
public XNode evalNode(String expression) {
// 从XML文档中抽取expression对应的内容
return evalNode(document, expression);
}
Step completed: "thread=main", org.apache.ibatis.parsing.XPathParser.evalNode(), line=217 bci=0
217 Node node = (Node) evaluate(expression, root, XPathConstants.NODE);
main[1] step
>
Step completed: "thread=main", org.apache.ibatis.parsing.XPathParser.evaluate(), line=226 bci=0
226 return xpath.evaluate(expression, root, returnType);
main[1] print xpath
xpath = "com.sun.org.apache.xpath.internal.jaxp.XPathImpl@3891771e"
main[1] print expression
expression = "/configuration"
main[1] print root
root = "[#document: null]"
main[1] print root.getClass()
root.getClass() = "class com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl"
main[1]
返回结果
Step completed: "thread=main", org.apache.ibatis.parsing.XPathParser.evalNode(), line=217 bci=9
217 Node node = (Node) evaluate(expression, root, XPathConstants.NODE);
main[1] step
>
Step completed: "thread=main", org.apache.ibatis.parsing.XPathParser.evalNode(), line=218 bci=13
218 if (node == null) {
main[1] print node
node = "[configuration: null]"
main[1] print node.getClass()
node.getClass() = "class com.sun.org.apache.xerces.internal.dom.DeferredElementImpl"
main[1]
拿到Configuration之后,第一步就是先执行
propertiesElement(root.evalNode("properties"));
我们来看看里面发生了什么?
public List<XNode> getChildren() {
//开始
List<XNode> children = new ArrayList<XNode>();
//遍历每一个Property节点
NodeList nodeList = node.getChildNodes();
if (nodeList != null) {
for (int i = 0, n = nodeList.getLength(); i < n; i++) {
Node node = nodeList.item(i);
//符合条件的话
if (node.getNodeType() == Node.ELEMENT_NODE) {
children.add(new XNode(xpathParser, node, variables));
}
}
}
return children;
//
}
children结果如下:
main[1] print children
children = "[<property name="driver" value="com.mysql.jdbc.Driver"/>
, <property name="url" value="jdbc:mysql://localhost:3306/test1"/>
, <property name="username" value="root"/>
, <property name="password" value="root"/>
]"
---
public Properties getChildrenAsProperties() {
//看到这里了
Properties properties = new Properties();
//开始遍历每一个child节点
for (XNode child : getChildren()) {
//取出name & value
String name = child.getStringAttribute("name");
String value = child.getStringAttribute("value");
if (name != null && value != null) {
//加入到properties中
properties.setProperty(name, value);
}
}
//返回
return properties;
}
最终properties结果为:
Step completed: "thread=main", org.apache.ibatis.parsing.XNode.getChildrenAsProperties(), line=313 bci=76
313 return properties;
main[1] print properties
properties = "{password=root, url=jdbc:mysql://localhost:3306/test1, driver=com.mysql.jdbc.Driver, username=root}"
main[1]
继续处理
private void propertiesElement(XNode context) throws Exception {
//看到这里了
if (context != null) {
//看到这里了
Properties defaults = context.getChildrenAsProperties();
//获取Properties中 resource属性值
String resource = context.getStringAttribute("resource");
//获取Properties中 url属性值
String url = context.getStringAttribute("url");
//竟然不可以同时存在
if (resource != null && url != null) {
throw new BuilderException(
"The properties element cannot specify both a URL and a resource based property file reference. Please specify one or the other.");
}
//如果resource合法
if (resource != null) {
//加入resource对应的属性
defaults.putAll(Resources.getResourceAsProperties(resource));
} else if (url != null) {
defaults.putAll(Resources.getUrlAsProperties(url));
}
//合入完毕
还剩下几行没有处理,继续
//合入完毕,还可以从configuration中获取啊...
Properties vars = configuration.getVariables();
if (vars != null) {
defaults.putAll(vars);
}
//继续处理
//回填
parser.setVariables(defaults);
//回填
configuration.setVariables(defaults);
//结束了
至此,Properties就处理完毕
总结如下:
1)从Properties块重构造
2)插入属性resource的值对应的文件内容
3)Properties vars = configuration.getVariables();
if (vars != null) {
defaults.putAll(vars);
}
依次执行构造内容,然后回填到需要的对象里。