首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > XML SOAP >

Spring底层施用SAX解析XML配置文件

2012-06-27 
Spring底层使用SAX解析XML配置文件最近在研究Spring源代码,在梳理spring-beans时故意只保留org.springfram

Spring底层使用SAX解析XML配置文件

最近在研究Spring源代码,在梳理spring-beans时故意只保留org.springframework.beans.factory.xml包下的xsd的3.1版本,然后在看Reference时,上面有一个简单的XML配置文件,如下

?

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">               <!-- beans --></beans>

?

?注意到这是一个3.0的xsd,然后测试时发现依然可以正常,只是变慢了,有时甚至卡住了,于是怀疑Spring底层代码访问了网址http://www.springframework.org/schema/beans/spring-beans-3.0.xsd,然后将返回的结果作为校验xml的xsd。

抽取了一部分ClassPathXmlApplicationContext加载过程的代码,仅仅解析XML配置文件,代码如下:

?

package test.temp;import java.io.InputStream;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.beans.factory.xml.DefaultDocumentLoader;import org.springframework.beans.factory.xml.DelegatingEntityResolver;import org.springframework.beans.factory.xml.DocumentLoader;import org.springframework.core.io.Resource;import org.springframework.core.io.support.EncodedResource;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import org.springframework.core.io.support.ResourcePatternResolver;import org.springframework.util.xml.SimpleSaxErrorHandler;import org.w3c.dom.Document;import org.xml.sax.EntityResolver;import org.xml.sax.ErrorHandler;import org.xml.sax.InputSource;public class Test2 {private static Log logger = LogFactory.getLog(Test2.class);public static void main(String[] args) throws Exception {String location = "a/a1.xml";////DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(null); //XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);//int counter = beanDefinitionReader.loadBeanDefinitions(location, null);//ResourcePatternResolver resourceLoader = new PathMatchingResourcePatternResolver();Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);for (Resource r : resources) {EncodedResource encodedResource = new EncodedResource(r);InputStream inputStream = encodedResource.getResource().getInputStream();InputSource inputSource = new InputSource(inputStream);// Resource resource = encodedResource.getResource();// // Key 2EntityResolver entityResolver = new DelegatingEntityResolver(null);ErrorHandler errorHandler = new SimpleSaxErrorHandler(logger);System.out.println("begin");DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();factory.setValidating(true); // Key 1factory.setNamespaceAware(true);factory.setAttribute("http://java.sun.com/xml/jaxp/properties/schemaLanguage", "http://www.w3.org/2001/XMLSchema");if (logger.isDebugEnabled()) {logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");}System.out.println("waiting...");DocumentBuilder docBuilder = factory.newDocumentBuilder();if (entityResolver != null) {docBuilder.setEntityResolver(entityResolver);}if (errorHandler != null) {docBuilder.setErrorHandler(errorHandler);}System.out.println("builder:[" + docBuilder + "]");// FIMXEDocument document = docBuilder.parse(inputSource);/*DocumentLoader documentLoader = new DefaultDocumentLoader();Document doc = documentLoader.loadDocument(inputSource, entityResolver, errorHandler, 3, false);*/System.out.println("end");}}}

?

?然后就开始一段痛苦而又折磨人的DEBUG之旅,使用Eclipse,设置端点,Spring使用SAX解析XML,SAX底层代码很复杂,调用极多,所以我就在F5,F6之间迷失了...还好,最终定位到

?

package com.sun.org.apache.xerces.internal.impl;...public class XMLDocumentScannerImpl        extends XMLDocumentFragmentScannerImpl{...    public void setInputSource(XMLInputSource inputSource) throws IOException {        fEntityManager.setEntityHandler(this);        //this starts a new entity and sets the current entity to the document entity.        fEntityManager.startDocumentEntity(inputSource);        // fDocumentSystemId = fEntityManager.expandSystemId(inputSource.getSystemId());        setScannerState(XMLEvent.START_DOCUMENT);    } // setInputSource(XMLInputSource)

?和

package com.sun.org.apache.xerces.internal.impl ;...public class XMLEntityManager implements XMLComponent, XMLEntityResolver {...public String setupCurrentEntity(String name, XMLInputSource xmlInputSource,            boolean literal, boolean isExternal)            throws IOException, XNIException {        // get information                final String publicId = xmlInputSource.getPublicId();        String literalSystemId = xmlInputSource.getSystemId();        String baseSystemId = xmlInputSource.getBaseSystemId();        String encoding = xmlInputSource.getEncoding();        final boolean encodingExternallySpecified = (encoding != null);        Boolean isBigEndian = null;                        // create reader        InputStream stream = null;        Reader reader = xmlInputSource.getCharacterStream();                // First chance checking strict URI        String expandedSystemId = expandSystemId(literalSystemId, baseSystemId, fStrictURI);        if (baseSystemId == null) {            baseSystemId = expandedSystemId;        }        if (reader == null) {            stream = xmlInputSource.getByteStream();            if (stream == null) {                URL location = new URL(expandedSystemId);                 URLConnection connect = location.openConnection();                if (!(connect instanceof HttpURLConnection)) {                    stream = connect.getInputStream();                }                else {                    boolean followRedirects = true;                                        // setup URLConnection if we have an HTTPInputSource                    if (xmlInputSource instanceof HTTPInputSource) {                        final HttpURLConnection urlConnection = (HttpURLConnection) connect;                        final HTTPInputSource httpInputSource = (HTTPInputSource) xmlInputSource;                                                // set request properties                        Iterator propIter = httpInputSource.getHTTPRequestProperties();                        while (propIter.hasNext()) {                            Map.Entry entry = (Map.Entry) propIter.next();                            urlConnection.setRequestProperty((String) entry.getKey(), (String) entry.getValue());                        }                                                // set preference for redirection                        followRedirects = httpInputSource.getFollowHTTPRedirects();                        if (!followRedirects) {                            setInstanceFollowRedirects(urlConnection, followRedirects);                        }                    }                                        stream = connect.getInputStream();                                        // REVISIT: If the URLConnection has external encoding                    // information, we should be reading it here. It's located                    // in the charset parameter of Content-Type. -- mrglavas                                        if (followRedirects) {                        String redirect = connect.getURL().toString();                        // E43: Check if the URL was redirected, and then                        // update literal and expanded system IDs if needed.                        if (!redirect.equals(expandedSystemId)) {                            literalSystemId = redirect;                            expandedSystemId = redirect;                        }                    }                }            }...

? 总算是验证的我的猜想 :)

另外在还在频繁的debug中发现,拔网线会产生异常,但抛出的异常并不是想象中的IOException,而是经过包装后的,乍一看是不知道网络连接失败导致的。

再另,如果classpath下有3.0的xsd,Spring就会直接使用它。

?

?

?

热点排行