首先按照正常的逻辑去解析一个 XML 配置文件;

    1. /**
    2. * 测试解析XML配置文件
    3. */
    4. public class ParseXMLTest {
    5. @Test
    6. public void parse() {
    7. try {
    8. // 1、获取XML资源
    9. InputStream in = new InputStreamResource(getClass().getResourceAsStream("test.xml")).getInputStream();
    10. // 2、获取DocumentBuilderFactory实例
    11. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    12. // 3、获取DocumentBuilder实例
    13. DocumentBuilder docBuilder = factory.newDocumentBuilder();
    14. // 4、将docBuilder转换为Document
    15. Document doc = docBuilder.parse(in);
    16. // 5、获取节点并循环输出节点值
    17. Element element = doc.getDocumentElement();
    18. NodeList childNodes = element.getChildNodes();
    19. // 解析,测试拿一些数据
    20. for (int i = 0; i < childNodes.getLength(); i++) {
    21. Node node = childNodes.item(i);
    22. NamedNodeMap attributesMap = node.getAttributes();
    23. if (null != attributesMap) {
    24. System.out.println(attributesMap.getNamedItem("id"));
    25. System.out.println(attributesMap.getNamedItem("class"));
    26. }
    27. }
    28. } catch (ParserConfigurationException | SAXException | IOException e) {
    29. e.printStackTrace();
    30. }
    31. }
    32. }

    例如一个配置文件如下所示:

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "https://www.springframework.org/dtd/spring-beans-2.0.dtd">
    3. <beans>
    4. <bean id="validEmptyWithDescription" class="org.springframework.beans.testfixture.beans.TestBean">
    5. <description>
    6. I have no properties and I'm happy without them.
    7. </description>
    8. </bean>
    9. <bean id="aliased" class=" org.springframework.beans.testfixture.beans.TestBean " name="myalias">
    10. <property name="name">
    11. <value>aliased</value>
    12. </property>
    13. </bean>
    14. <alias name="aliased" alias="youralias"/>
    15. <alias name="multiAliased" alias="alias3"/>
    16. <bean id="multiAliased" class="org.springframework.beans.testfixture.beans.TestBean" name="alias1,alias2">
    17. <property name="name">
    18. <value>aliased</value>
    19. </property>
    20. </bean>
    21. </beans>

    接下来看一下 Spring 是如何处理这个解析的:
    从这开始:XmlBeanDefinitionReader#doLoadDocument

    1. protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
    2. return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
    3. getValidationModeForResource(resource), isNamespaceAware());
    4. }

    再进入 DefaultDocumentLoader#loadDocument 可以看出利用方法 createDocumentBuilderFactory 得到解析工厂;
    然后利用 createDocumentBuilder 方法得到解析器;
    这两个方法和我们上面的测试代码几乎是一样的,只不过是多了一些校验和回调方法;

    1. @Override
    2. public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
    3. ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
    4. DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
    5. if (logger.isTraceEnabled()) {
    6. logger.trace("Using JAXP provider [" + factory.getClass().getName() + "]");
    7. }
    8. DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
    9. return builder.parse(inputSource);
    10. }

    最终 builder.parse(inputSource);
    解析 XML 得到 Document;