总文档 :文章目录
Github : github.com/black-ant
一 . 前言
第二篇 IOC 的文章还是挑一个软柿子捏 , 这一篇说一说 Resource 和 Document 的加载方式 , 也是比较简单的东西.
扫描部分的体系包括 Resource , Document ,Annotation 几部分 , 这里只说前面2种
二 . Resource 体系篇
Resource 是一切的基础 , 所有的外部对象都可以看成一个 Resource , 为此 Spring 提供了很多 Resource 的实现类 :
常见的 Resource 主要是用于以下功能:
1 | java复制代码// 当用不同的 ResourceLoader 加载资源的时候 , 会根据资源类型的不同 , 选择生成不同的 Resource |
Resource 体系功能 :
1 | java复制代码// 统一资源的核心类是 : Resource , 为 Spring 框架所有资源的抽象和访问接口 |
Resource 接口的实现
1 | java复制代码 |
Resource 会通过 ResourceLoader 进行加载 , 重要的 ResourceLoader 包含如下结构 :
需要注意的是 : ApplicationContext 基本上都是 ResourceLoader 的实现类 , 所以他们通常带有ResourceLoader 的功能
ResourceLoader加载体系
1 | java复制代码 |
一个 Resource 加载流程中涉及的主要类
1 | java复制代码// XML 流程 Resource 加载 , 我们还是从 BeanDefinitionReader 开始看起 |
加载 Resource 的几个场景 , 通常可以由 location 看出来
类型一 : classpath*:com/gang/study/source/springboot/demo/**/*.class
1 | java复制代码//这种路径 , 其源头为 ComponentScanAnnotationParser 开始 , 更早的源头是 Configuration 的相关扫描逻辑 |
前置资源的加载 :
M153_01M155_03M201_03M17_02ComponentScan 扫描类路径doScan 扫描路径调用 PathMatchingResourcePatternResolver 获取 resourceM153_01M155_03M201_03M17_02
Resource 资源的加载 :
- M17_02 : getResources
- M17_03 : findPathMatchingResources
- M17_04 : findAllClassPathResources
- M17_05 : doFindAllClassPathResources
M17_02M17_03M17_04M17_05发现是 待匹配的classpath resource 调用 findPathMatchingResources递归 Resource回调 getResources发现为 classPath 调用findAllClassPathResources返回具体的classPath 即 URLReource (实际)调用 classloader 扫描具体的类对象返回对象 , 放入集合M17_02M17_03M17_04M17_05
核心逻辑就是 :
- 如果路径是待匹配的 : findPathMatchingResources
- 其中通过匹配 , 调用 findAllClassPathResources 获取真实路径
- 通过真实路径 , 调用 doFindAllClassPathResources 获取具体的类 Resource
类型二 : classpath*:messages.properties 资源加载
前置资源的加载 :
1 | java复制代码 |
M202_02M17_02M17_04获取 classpath*:messages.properties无需匹配 , 直接 调用 findAllClassPathResources返回资源对于 URLResourceConfiguration 使用资源M202_02M17_02M17_04
类型三 : xml 类型资源
以 classpath:spring-common.xml为例
1 | java复制代码 |
PS: 至于其他的不具有代表性 , 就不详细说了
三 . Document 体系篇
当统一资源加载完成后 , 其中的 xml 类型会被处理为 Document 对象
Document 扫描是指对文档体系的扫描 , 主要用于xml 方式配置 Bean 时
PS : 说一句 , 早期的时候我也觉得说 XML 配置很陈旧 , 是过时的方法 , 但是现在反而有种不一样的感觉 , 相比Configuration 方式 ,它的条理更清晰 , 用起来其实也不复杂
Document 体系功能
我们先看下 Doument 的常见方法功能 :
作用 : 用于处理 Document 文档类型对象 , 包括 .xml , .dto , .schemas 等
起源 : XmlBeanDefinitionReader#doLoadDocument(InputSource inputSource, Resource resource) 方法
- 该方法做了2件事
- 调用 #getValidationModeForResource(Resource resource) 方法,获取指定资源(xml)的验证模式
- 调用 DocumentLoader#loadDocument 获取 XML Document 实例
1 | java复制代码C25- DocumentLoader : 获取 Document 的策略,由接口 org.springframework.beans.factory.xml.DocumentLoader 定义 |
Document 扫描跟踪 :
1 | java复制代码 |
DocumentBuilder
1 | java复制代码DocumentBuilder 是一个抽象类 , 其主要 实现是 DocumentBuilderImpl |
完整 Document 处理流程图
1 | java复制代码// Step 1 : ConfigurationClassBeanDefinitionReader # loadBeanDefinitions |
M21_01M21_02M26_01M24_01加载 bean.xml , 获得对象的 resource 文件doLoadDocument 处理 resource 对象DocumentBuilderFactory -> DocumentBuilder 加载document解析 Document返回 Document 对象处理 document 对象 -> registerBeanDefinitionsM21_01M21_02M26_01M24_01
扩展 EntityResolver 对象
EntityResolver 对象用于对 Document 进行解析 , 现在常见的有这几种 :
参考文档 @ cmsblogs.com/?p=2695
- ResourceEntityResolver:继承自 EntityResolver ,通过 ResourceLoader 来解析实体的引用。
- DelegatingEntityResolver:EntityResolver 的实现,分别代理了 dtd 的 BeansDtdResolver 和 xml schemas 的 PluggableSchemaResolver。
- BeansDtdResolver : spring bean dtd 解析器。EntityResolver 的实现,用来从 classpath 或者 jar 文件加载 dtd。
- PluggableSchemaResolver:使用一系列 Map 文件将 schema url 解析到本地 classpath 资源
1 | java复制代码protected EntityResolver getEntityResolver() { |
补充 Document 功能
Document 主要就是为了将 XML 解释为可读对象
补充 DTD 和 XSD
参考文档 @ cmsblogs.com/?p=2688 , 建议看看原版 , 这里摘取些关键环节
DTD(Document Type Definition),即文档类型定义,为 XML 文件的验证机制,属于 XML 文件中组成的一部分。
DTD 是一种保证 XML 文档格式正确的有效验证方式,它定义了相关 XML 文档的元素、属性、排列方式、元素的内容类型以及元素的层次结构。其实 DTD 就相当于 XML 中的 “词汇”和“语法”,我们可以通过比较 XML 文件和 DTD 文件 来看文档是否符合规范,元素和标签使用是否正确。 要在 Spring 中使用 DTD,需要在 Spring XML 文件头部声明:
1 | java复制代码<?xml version="1.0" encoding="UTF-8"?> |
DTD 在一定的阶段推动了 XML 的发展,但是它本身存在着一些缺陷:
- 它没有使用 XML 格式,而是自己定义了一套格式,相对解析器的重用性较差;
- DTD 的构建和访问没有标准的编程接口,因而解析器很难简单的解析 DTD 文档。
- DTD 对元素的类型限制较少;同时其他的约束力也叫弱。
- DTD 扩展能力较差。
- 基于正则表达式的 DTD 文档的描述能力有限。
XSD 具有如下优势
针对 DTD 的缺陷,W3C 在 2001 年推出 XSD。XSD(XML Schemas Definition)即 XML Schema 语言。XML Schema 本身就是一个 XML文档,使用的是 XML 语法,因此可以很方便的解析 XSD 文档。
- XML Schema基于XML,没有专门的语法
- XML Schema可以象其他XML文件一样解析和处理
- XML Schema比DTD提供了更丰富的数据类型.
- XML Schema提供可扩充的数据模型。
- XML Schema支持综合命名空间
- XML Schema支持属性组。
不同的验证模式使用不同的解析器解析 :
ValidationMode 的验证位置
1 | JAVA复制代码 |
总结
Resource 和 Document 的扫描收集是一切的基础 ,当2者采集完全后 , 就可以开始相关类的加载工作了
本文转载自: 掘金