preg_match 参数获取两个_「死磕 Spring」—– IOC 之 获取 Document 对象
原文出自:http://cmsblogs.com作者:chenssy
在 XmlBeanDefinitionReader.doLoadDocument() 方法中做了两件事情,一是调用 getValidationModeForResource() 获取 XML 的验证模式,二是调用 DocumentLoader.loadDocument() 获取 Document 对象。上篇博客已经分析了获取 XML 验证模式(【死磕Spring】----- IOC 之 获取验证模型),这篇我们分析获取 Document 对象。 获取 Document 的策略由接口 DocumentLoader 定义,如下:
public interface DocumentLoader { Document loadDocument( InputSource inputSource, EntityResolver entityResolver, ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception;}
DocumentLoader 中只有一个方法
loadDocument() ,该方法接收五个参数: * inputSource:加载 Document 的 Resource 源 * entityResolver:解析文件的解析器 * errorHandler:处理加载 Document 对象的过程的错误 * validationMode:验证模式 * namespaceAware:命名空间支持。如果要提供对 XML 名称空间的支持,则为true 该方法由 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); }
首先调用
createDocumentBuilderFactory() 创建 DocumentBuilderFactory ,再通过该 factory 创建 DocumentBuilder,最后解析 InputSource 返回 Document 对象。
EntityResolver 通过
loadDocument() 获取 Document 对象时,有一个参数 entityResolver ,该参数是通过 getEntityResolver() 获取的。
getEntityResolver() 返回指定的解析器,如果没有指定,则构造一个未指定的默认解析器。
protected EntityResolver getEntityResolver() { if (this.entityResolver == null) { ResourceLoader resourceLoader = getResourceLoader(); if (resourceLoader != null) { this.entityResolver = new ResourceEntityResolver(resourceLoader); } else { this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader()); } } return this.entityResolver; }
如果 ResourceLoader 不为 null,则根据指定的 ResourceLoader 创建一个 ResourceEntityResolver。如果 ResourceLoader 为null,则创建 一个 DelegatingEntityResolver,该 Resolver 委托给默认的 BeansDtdResolver 和 PluggableSchemaResolver 。
- ResourceEntityResolver:继承自 EntityResolver ,通过 ResourceLoader 来解析实体的引用。
- DelegatingEntityResolver:EntityResolver 的实现,分别代理了 dtd 的 BeansDtdResolver 和 xml schemas 的 PluggableSchemaResolver。
- BeansDtdResolver : spring bean dtd 解析器。EntityResolver 的实现,用来从 classpath 或者 jar 文件加载 dtd。
- PluggableSchemaResolver:使用一系列 Map 文件将 schema url 解析到本地 classpath 资源
getEntityResolver() 返回 EntityResolver ,那这个 EntityResolver 到底是什么呢?
If a SAX application needs to implement customized handling for external entities, it must implement this interface and register an instance with the SAX driver using the setEntityResolver method.就是说:如果 SAX 应用程序需要实现自定义处理外部实体,则必须实现此接口并使用 setEntityResolver() 向 SAX 驱动器注册一个实例。 如下:
public class MyResolver implements EntityResolver { public InputSource resolveEntity (String publicId, String systemId){ if (systemId.equals("http://www.myhost.com/today")){ MyReader reader = new MyReader(); return new InputSource(reader); } else { // use the default behaviour return null; } } }
我们首先将
spring-student.xml 文件中的 XSD 声明的地址改掉,如下:
如果我们再次运行,则会报如下错误:
从上面的错误可以看到,是在进行文档验证时,无法根据声明找到 XSD 验证文件而导致无法进行 XML 文件验证。在(【死磕Spring】----- IOC 之 获取验证模型)中讲到,如果要解析一个 XML 文件,SAX 首先会读取该 XML 文档上的声明,然后根据声明去寻找相应的 DTD 定义,以便对文档进行验证。默认的加载规则是通过网络方式下载验证文件,而在实际生产环境中我们会遇到网络中断或者不可用状态,那么就应用就会因为无法下载验证文件而报错。
EntityResolver 的作用就是应用本身可以提供一个如何寻找验证文件的方法,即自定义实现。 接口声明如下:
public interface EntityResolver { public abstract InputSource resolveEntity (String publicId,String systemId) throws SAXException, IOException;}
接口方法接收两个参数 publicId 和 systemId,并返回 InputSource 对象。两个参数声明如下:
- publicId:被引用的外部实体的公共标识符,如果没有提供,则返回null
- systemId:被引用的外部实体的系统标识符 这两个参数的实际内容和具体的验证模式有关系。如下
- XSD 验证模式
- publicId:null
- systemId:http://www.springframework.org/schema/beans/spring-beans.xsd
- DTD 验证模式
- publicId:-//SPRING//DTD BEAN 2.0//EN
- systemId:http://www.springframework.org/dtd/spring-beans.dtd 如下:
我们知道在 Spring 中使用 DelegatingEntityResolver 为 EntityResolver 的实现类,resolveEntity() 实现如下:
public InputSource resolveEntity(String publicId, @Nullable 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; }
不同的验证模式使用不同的解析器解析,如果是 DTD 验证模式则使用 BeansDtdResolver 来进行解析,如果是 XSD 则使用 PluggableSchemaResolver 来进行解析。 BeansDtdResolver 的解析过程如下:
从上面的代码中我们可以看到加载 DTD 类型的
BeansDtdResolver.resolveEntity() 只是对 systemId 进行了简单的校验(从最后一个 / 开始,内容中是否包含 spring-beans),然后构造一个 InputSource 并设置 publicId、systemId,然后返回。 PluggableSchemaResolver 的解析过程如下:
首先调用 getSchemaMappings() 获取一个映射表(systemId 与其在本地的对照关系),然后根据传入的 systemId 获取该 systemId 在本地的路径 resourceLocation,最后根据 resourceLocation 构造 InputSource 对象。 映射表如下(部分):
preg_match 参数获取两个_「死磕 Spring」—– IOC 之 获取 Document 对象相关推荐
- 【死磕 Spring】----- IOC 之 Factory 实例化 bean
原文:https://www.cmsblogs.com/category/1391374860344758272 『chenssy』 这篇我们关注创建 bean 过程中的第一个步骤:实例化 bean, ...
- 【死磕 Spring】----- IOC 之 加载 Bean
原文:https://www.cmsblogs.com/category/1391374860344758272 『chenssy』 先看一段熟悉的代码: ClassPathResource reso ...
- 【死磕 Spring】—– IOC 之 Factory 实例化 bean
这篇我们关注创建 bean 过程中的第一个步骤:实例化 bean,对应的方法为: createBeanInstance(),如下: protected BeanWrapper createBeanIn ...
- WPS如何并排放置两张图片_「WPS办公助手」想做出高级又好看的 PPT,这个炫酷的功能你可别错过...
如果有人问我,有没有方法可以让 PPT 变得好看且更高级,我第一时间想到的就是它. 话不多说,直接上图: 这起源于keynote的"神奇移动",它可以使PPT里的元素实现非常炫酷的 ...
- 【死磕 Spring】----- IOC 之解析 bean 标签:解析自定义标签
前面四篇文章都是分析 Bean 默认标签的解析过程,包括基本属性.六个子元素(meta.lookup-method.replaced-method.constructor-arg.property.q ...
- 【死磕 Spring】—– 死磕 Spring 精品合集
Java面经 2019-03-05 09:00:40 原文:http://cmsblogs.com/?cat=206 [死磕 Spring]-– IOC 之深入理解 Spring IoC [死磕 Sp ...
- 「死磕Java并发编程」说说Java Atomic 原子类的实现原理
<死磕 Java 并发编程>系列连载中,大家可以关注一波. 「死磕 Java 并发编程」阿里二面,面试官:说说 Java CAS 原理? 「死磕 Java 并发编程」面试官:说说什么是 J ...
- [死磕 Spring 21/43] --- IOC 之 Factory 实例化 bean
引用原文: https://www.cmsblogs.com/article/1391375394573258752 [死磕 Spring 21/43] - IOC 之 Factory 实例化 bea ...
- 死磕Spring AOP系列2:剖析Bean处理器之BeanNameAutoProxyCreator
通过前一篇<死磕Spring AOP系列1:编程式实现AOP>,学习了Spring对代理的底层支持,认识了ProxyFactory对象,及从类设计层面认识了PointCut&Adv ...
最新文章
- # 关闭 window10自带广告 microsoft star
- unable to get repr for class ‘torch.tensor‘
- Log4j每天、每小时、每分钟定时生成日志文件
- 大页(Huge Page)简单介绍
- 编号003099--ORACLE DBA-SH/WH
- 红米airdots掉了怎么查找_红米K30至尊版与realmeX7 Pro,两款性价比手机,谁才是第一位...
- Qt CMake变量参考
- 搭建kafaka_Kafka 环境部署搭建
- python默认参数只被解释一次_深入讲解Python函数中参数的使用及默认参数的陷阱...
- Mac OS修改VSCode Go的默认缩进格式
- Solr学习笔记001---solr在windows下的安装及配置
- html模块常用命名总结
- 存储设备在linux名称,Linux下的存储设备的管理
- 大学计算机应用与基础第二版答案,大学计算机应用基础(第2版)上机指导与习题集...
- 在LaTeX中使用Python highlighting in LaTeX让python代码高亮
- 思维的基本过程与解决问题
- android教你打造独一无二的图片加载框架
- 学Python好找工作吗?需要满足Python岗位哪些要求?
- 机器学习:SVR支持向量机回归
- 网页底部版权信息如何注明?
热门文章
- 开源与安全兼备 IBM LinuxONE轻松掌控关键业务
- 一个数据科学家对商学院的建议
- redhat 6.5 vnc 配置
- 读书笔记_Effective_C++_条款二十四: 若所有参数皆需类型转换,请为此采用non-member函数...
- linux下用cronolog分割apache日志
- 2018腾讯内部转岗面试题2——打印A-Z 26个字母的所有子集
- web前端开发初学者十问集锦(3)
- C++ 动态联编实现原理分析
- 去除QQ打/之后会出现的表情
- 裘宗燕:C/C++ 语言中的表达式求值