spring源码深度解析笔记(五)

通过了验证模式准备的不走就可以进行Document加载了。同样XmlBeanFactoryReader类对于文档读取并没有亲力亲为,而是委托了DocumentLoader去执行。这里的DocumentLoader是个借口。而真正调用的是DefaultDocumentLoader。

public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
            ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {

        DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
        if (logger.isDebugEnabled()) {
            logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");
        }
        DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
        return builder.parse(inputSource);
    }

这段代码通过SAX解析XML文档。首先创建DocumentBuiderFactory,在通过DocumentBuilderFactory创建DocumentBuilder。进行解析inputSource来返回Document对象。
在loadDocument方法中涉及一个参数EntityResolver,那什么是EntityResovler呢?
EntityResolver的作用是项目本身就可以提供一个如何寻找DTD声明的方法,既有程序来实现寻找DTD声明的过程。比如我们将DTD文件放在项目中的某处。在实现时直接将此文档读取返回给sax即可。这样就避免了通过网络来寻找相应的声明。
首先看entityResolver的接口方法声明:

protected EntityResolver getEntityResolver() {
        if (this.entityResolver == null) {
            // Determine default EntityResolver to use.
            ResourceLoader resourceLoader = getResourceLoader();
            if (resourceLoader != null) {
                this.entityResolver = new ResourceEntityResolver(resourceLoader);
            }
            else {
                this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader());
            }
        }
        return this.entityResolver;
    }

    public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
        if (systemId != null) {
            if (systemId.endsWith(DTD_SUFFIX)) {
                return this.dtdResolver.resolveEntity(publicId, systemId);
            }
            else if (systemId.endsWith(XSD_SUFFIX)) {
                return this.schemaResolver.resolveEntity(publicId, systemId);
            }
        }
        return null;
    }

对于不同的验证模式,Spring使用了不同的解析器解析。

public InputSource resolveEntity(String publicId, String systemId) throws IOException {
        if (logger.isTraceEnabled()) {
            logger.trace("Trying to resolve XML entity with public ID [" + publicId +
                    "] and system ID [" + systemId + "]");
        }
        if (systemId != null && systemId.endsWith(DTD_EXTENSION)) {
            int lastPathSeparator = systemId.lastIndexOf("/");
            for (String DTD_NAME : DTD_NAMES) {
                int dtdNameStart = systemId.indexOf(DTD_NAME);
                if (dtdNameStart > lastPathSeparator) {
                    String dtdFile = systemId.substring(dtdNameStart);
                    if (logger.isTraceEnabled()) {
                        logger.trace("Trying to locate [" + dtdFile + "] in Spring jar");
                    }
                    try {
                        Resource resource = new ClassPathResource(dtdFile, getClass());
                        InputSource source = new InputSource(resource.getInputStream());
                        source.setPublicId(publicId);
                        source.setSystemId(systemId);
                        if (logger.isDebugEnabled()) {
                            logger.debug("Found beans DTD [" + systemId + "] in classpath: " + dtdFile);
                        }
                        return source;
                    }
                    catch (IOException ex) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in class path", ex);
                        }
                    }

                }
            }
        }

        // Use the default behavior -> download from website or wherever.
        return null;
    }

加载DTD类型的beansDtdResolver的resolveEntity是直接截取systemId最后的xx.dtd然后去当前路径下寻找,而加载xsd类型的pluggableschemaResolver类resolveEntity是默认到META-INF/Spring.schemas文件中找到systemid所对应的xsd文件加载。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值