美文网首页
2-XML 配置文件读取——2-3 自定义相关配置属性的解析

2-XML 配置文件读取——2-3 自定义相关配置属性的解析

作者: 鹏程1995 | 来源:发表于2020-02-25 11:20 被阅读0次

    概要

    过度

    我们要介绍的是 :

    1. Spring 读取 xml 配置文件并生成对应的保存 Bean 定义信息的数据结构——BeanDefinition并注册
    2. 注册完成后根据指定的信息,创建 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));
    }
    

    思路很简单:

    1. 获得元素的命名空间
    2. 根据命名空间从上下文中获得专门负责注册解析器并提供解析元素服务的类NamespaceHandlerResolver
    3. 根据命名空间和NamespaceHandlerResolver获得处理此节点的NamespaceHandler
    4. 直接委托给确定的handler进行元素解析

    参考对应的数据结构

    此处需要深入了解NamespaceHandlerResolverNamespaceHandler两个类。

    参考类列表:

    • NamespaceHandlerResolver
    • DefaultNamespaceHandlerResolver
    • NamespaceHandler
    • NameSpaceHandlerSupport
    • BeanDefinitionParser
    • AbstractBeanDefinitionParser
    • AbstractSingleBneaDefinitionParser

    扩展

    已经自行实现对应代码,参考代码:https://github.com/LiPengcheng1995/spring-framework-exercise.git

    示例 model : learn-parse-costume-element

    问题遗留

    参考文献

    相关文章

      网友评论

          本文标题:2-XML 配置文件读取——2-3 自定义相关配置属性的解析

          本文链接:https://www.haomeiwen.com/subject/vkpzqhtx.html