10.2.2. 编码一个NamespaceHandler

除了模式之外,我们还需要NamespaceHandler解析 Spring 在解析配置文件时遇到的这个特定命名空间的所有元素。对于这个例子, NamespaceHandler应该负责myns:dateformat 元素的解析。

NamespaceHandler接口具有三种方法:

  • init(): 允许初始化 NamespaceHandler 并在使用处理程序之前由 Spring 调用。

  • BeanDefinition parse(Element, ParserContext):当 Spring 遇到顶级元素(未嵌套在 bean 定义或不同的命名空间内)时调用。此方法本身可以注册 bean 定义、返回 bean 定义或两者兼而有之。

  • BeanDefinitionHolder decorate(Node, BeanDefinitionHolder, ParserContext):当 Spring 遇到不同命名空间的属性或嵌套元素时调用。一个或多个 bean 定义的装饰(例如)与 Spring 支持的范围一起使用。我们首先突出一个简单的例子,不使用装饰,然后我们在一个更高级的例子中展示装饰。

尽管您可以为整个命名空间编写自己的NamespaceHandler代码(并因此提供解析命名空间中每个元素的代码),但通常情况下,Spring XML 配置文件中的每个顶级 XML 元素都会导致单个 bean 定义(在我们的例子中,单个<myns:dateformat/> 元素导致单个SimpleDateFormatbean 定义)。Spring 提供了许多支持这种场景的便利类。在以下示例中,我们使用NamespaceHandlerSupport该类:

package org.springframework.samples.xml;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

public class MyNamespaceHandler extends NamespaceHandlerSupport {

    public void init() {
        registerBeanDefinitionParser("dateformat", new SimpleDateFormatBeanDefinitionParser());
    }
}

您可能会注意到,此类中实际上并没有很多解析逻辑。事实上,NamespaceHandlerSupport 类有一个内置的委托概念。它支持注册任意数量的BeanDefinitionParser实例,当需要解析其名称空间中的元素时,它会委托给这些实例。这种干净的关注点分离让 NamespaceHandler 能够处理其命名空间中所有自定义元素的解析编排,同时委托 BeanDefinitionParsers 来完成 XML 解析的繁重工作。这意味着每个BeanDefinitionParser仅包含解析单个自定义元素的逻辑,正如我们在下一步中看到的那样。

最后更新于