首先按照正常的逻辑去解析一个 XML 配置文件;
/*** 测试解析XML配置文件*/public class ParseXMLTest {@Testpublic void parse() {try {// 1、获取XML资源InputStream in = new InputStreamResource(getClass().getResourceAsStream("test.xml")).getInputStream();// 2、获取DocumentBuilderFactory实例DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();// 3、获取DocumentBuilder实例DocumentBuilder docBuilder = factory.newDocumentBuilder();// 4、将docBuilder转换为DocumentDocument doc = docBuilder.parse(in);// 5、获取节点并循环输出节点值Element element = doc.getDocumentElement();NodeList childNodes = element.getChildNodes();// 解析,测试拿一些数据for (int i = 0; i < childNodes.getLength(); i++) {Node node = childNodes.item(i);NamedNodeMap attributesMap = node.getAttributes();if (null != attributesMap) {System.out.println(attributesMap.getNamedItem("id"));System.out.println(attributesMap.getNamedItem("class"));}}} catch (ParserConfigurationException | SAXException | IOException e) {e.printStackTrace();}}}
例如一个配置文件如下所示:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "https://www.springframework.org/dtd/spring-beans-2.0.dtd"><beans><bean id="validEmptyWithDescription" class="org.springframework.beans.testfixture.beans.TestBean"><description>I have no properties and I'm happy without them.</description></bean><bean id="aliased" class=" org.springframework.beans.testfixture.beans.TestBean " name="myalias"><property name="name"><value>aliased</value></property></bean><alias name="aliased" alias="youralias"/><alias name="multiAliased" alias="alias3"/><bean id="multiAliased" class="org.springframework.beans.testfixture.beans.TestBean" name="alias1,alias2"><property name="name"><value>aliased</value></property></bean></beans>
接下来看一下 Spring 是如何处理这个解析的:
从这开始:XmlBeanDefinitionReader#doLoadDocument
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,getValidationModeForResource(resource), isNamespaceAware());}
再进入 DefaultDocumentLoader#loadDocument 可以看出利用方法 createDocumentBuilderFactory 得到解析工厂;
然后利用 createDocumentBuilder 方法得到解析器;
这两个方法和我们上面的测试代码几乎是一样的,只不过是多了一些校验和回调方法;
@Overridepublic Document loadDocument(InputSource inputSource, EntityResolver entityResolver,ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);if (logger.isTraceEnabled()) {logger.trace("Using JAXP provider [" + factory.getClass().getName() + "]");}DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);return builder.parse(inputSource);}
最终 builder.parse(inputSource);
解析 XML 得到 Document;
