概要
过度
我们要介绍的是 :
- Spring 读取 xml 配置文件并生成对应的保存 Bean 定义信息的数据结构——
BeanDefinition
并注册 - 注册完成后根据指定的信息,创建 Bean 实例并返回
我们之前第一篇文章介绍了 Spring 读取 xml 配置文件的一些资源加载和准备工作,最后以即将进行具体的 DOM 树解析来结尾。
我们接下来开始介绍具体的 DOM 节点的解析工作:
我们之前第二篇文章介绍了 Spring 命名空间的的标签的解析工作。
所以,我们接下来要进行的是介绍非 Spring 命名空间的标签的解析工作。
内容简介
本文主要介绍非 Spring 命名空间的标签的解析原理。因为这个功能并不是完全由 Spring 框架实现的功能,是提供给依赖 Spring 的框架/使用 Spring 的 用户使用的。
所以我们本节先介绍 Spring 框架的对外部命名空间的解析器调用原理,介绍完成后会根据调用原理介绍如何自定义命名空间并定义该命名空间的解释器,然后将解释器注册以实现其功能。
所属环节
XML 配置文件读取中的 Spring DOM 节点解析。
上下环节
上文:XML 配置文件读入,XML 文件校验
下文:根据需求创建 Bean实例
源码解析
入口
/**
* Parse the elements at the root level in the document:
* "import", "alias", "bean".
*
* @param root the DOM root element of the document
*/
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
} else {
delegate.parseCustomElement(ele);
}
}
}
} else {
delegate.parseCustomElement(root);
}
}
我们上面讲到了这里,这里根据命名空间,将解析出来的 DOM 分别交给 Spring 自己的解析器或者在 Spring 中注册的第三方解析器。我们本文专注看第二种情况。
委托给专门的数据结构解析器
这里我们进去看一下delegate.parseCustomElement(ele)
。这里其实很简单,因为我们是调用的BeanDefinitionParserDelegate
的方法,上下文的相关信息默认就传进去了。他的实现思路也很简单,先贴代码:
@Nullable
public BeanDefinition parseCustomElement(Element ele) {
return parseCustomElement(ele, null);
}
@Nullable
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
思路很简单:
- 获得元素的命名空间
- 根据命名空间从上下文中获得专门负责注册解析器并提供解析元素服务的类
NamespaceHandlerResolver
- 根据命名空间和
NamespaceHandlerResolver
获得处理此节点的NamespaceHandler
- 直接委托给确定的
handler
进行元素解析
参考对应的数据结构
此处需要深入了解NamespaceHandlerResolver
和NamespaceHandler
两个类。
参考类列表:
NamespaceHandlerResolver
DefaultNamespaceHandlerResolver
NamespaceHandler
NameSpaceHandlerSupport
BeanDefinitionParser
AbstractBeanDefinitionParser
AbstractSingleBneaDefinitionParser
扩展
已经自行实现对应代码,参考代码:https://github.com/LiPengcheng1995/spring-framework-exercise.git
示例 model : learn-parse-costume-element
网友评论