引子
系列1 - bean 标签解析:
3、XmlBeanFactory 对xml文件读取.md
5、xml配置文件解析之【自定义】命名空间【标签】的解析.md
前言
还是老规矩,先一句话概括本文干了啥:
- 配置 Bean的 xml 文件读取
- xml 文件内容、格式校验: DTD / XSD
- 将 xml 配置的内容,解析为 BeanDefinition,注册到 "Bean 工厂" XmlBeanfactory 中
1 跟随 XmlBeanFactory 的构造方法逐步跳转:
2 parentFactory 的处理
super(parentFactory;
3 XmlBeanDefinitionReader
后继者 的解析结果,最终肯定会注册到 XmlBeanFactory 上的。
4 从文件流读取内容
5 至关重要的两行代码
6 第一行做的事,就是前边提到的 xml 格式校验
6.1 识别 xml 文件的校验模式
-
在 XmlBeanFactory 的场景瞎,XmlBeanDefinitionReader 是 XmlBeanFactory 的成员变量。
如果我们反向跟踪瞎,谁调用过: setValidationMode( 方法,找到了下图中的:XmlWebApplicationContext,这就说明在这个容器里,是支持动态设置xml校验模式的。
-
BeanFactory" 没有预置 xml 校验模式,就会去扫描 xml 配置文件,读取其中配置的是:dtd 或者 xsd文件
- 这里会逐行读取xml 文件,从中提取xml 的校验方式
6.2 校验模式识别后,就是加载配置
this.documentLoader.loadDocument(xx,xxx,xx...。
- 就是根据检验模式校验文件
- 校验通过后返回一个Document 对象,其实常规的 Xml 读取应该也是类似的套路。
7 第二行在校验通过后正式开始解析
本节要做的事就是从该 Document对象中,读取BeanDefinition 【Bean定义/配置信息】
parseBeanDefinitions(root, this.delegate;
下图中,我添加的注释里,提到了两个关键词:
- 指的是 spring 官方支持的 xml 配置文件的元素和标签
-
自定义命名空间:
- 属于开发者个人对spring的个性化魔改。
默认命名空间:
- parseBeanDefinitions(root, this.delegate方法会完成 xml 解析
- 最终的解析结果将会被: XmlBeanFactory (BeanDefinitionRegistry接口) 持有
- 当从 XmlBeanFactory 调用 getBean( 时,就会从 BeanDefinitionRegistry接口管理的配置信息中,获取到相关类的信息
- 最后利用类信息 + 反射技术,得到 类的实例对象,并且,该对象(Bean 将会被 XmlBeanFactory (BeanFactory接口 管理
8 后话
至于为什么我在第七章末尾说:xml最终的解析结果被 XmlBeanFactory (BeanDefinitionRegistry接口) 持有呢?
8.1 XmlBeanFactory 的第一次传递
前文提到过,在 XmlBeanFactory 类中初始化 reader 时调用了 XmlBeanDefinitionReader 的构造函数,这里已经把 XmlBeanFactory 自身作为参数传递进去了。
- registry
8.2 XmlBeanFactory 的第二次传递
这个引用关系传递得非常隐蔽:
回过头去看 [第7章] 的第一个图,Document 的处理被委托给了一个别的类:
// 这里 documentReader 还特么是个局部变量
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(;
从这里可以得知,xml解析方法的调用链,已经离开 XmlBeanFactory.reader[XmlBeanDefinitionReader] 内部了;
真的是这样吗,看下图的 createReaderContext 方法标注的内容:
XmlBeanDefinitionReader.createReaderContext( 方法内,创建 XmlReaderContext 实例对象时,传递的 "this" 的 成员变量 registry 就是我们的 XmlBeanFactory 的对象实例。
8.3 XmlBeanFactory 的第三次传递
到本文 [第7章] 的最后,Xml 的解析又被委托给了:
- BeanDefinitionParserDelegate
先说说 parentDelegate = this.delegate,在我们当前场景下没有做出任何额外的配置动作,这里获取到的会是个空值:null
- getReaderContext(
它获取到的,就是上一节提到的,用 XmlBeanDefinitionReader 封装的 XmlReaderContext 对象。
XmlReaderContext 又一次悄悄的潜入到了, Xml 标签/元素 解析的 "代理类" 内部了。
悄悄的进村,打枪的不要,哈哈。
BeanDefinitionParserDelegate(
.XmlReaderContext(
.BeanDefinitionDocumentReader(
.XmlBeanFactory(
下一篇文章将会花一定篇幅,介绍spring的 xml 配置文件中定义的元素、标签的读取。