Spring系列-XML schema扩展机制

原文地址:www.jianshu.com/p/8639e5e9f…

从Spring 2.0版本开始,Spring提供了XML Schema可扩展机制,用于定义和配置Bean。完成XML自定义扩展,需要下面几个步骤:

  1. 创建一个 XML Schema 文件,描述自定义的合法构建模块,也就是xsd文件。
  2. 自定义个处理器类,并实现NamespaceHandler接口。
  3. 自定义一个或多个解析器,实现BeanDefinitionParser接口(最关键的部分)。
  4. 注册上面的组件到Spring IOC容器中。

按照上面的步骤,实现如下可扩展XML元素:

<myns:dateformat id="dateFormat" pattern="yyyy-MM-dd HH:mm" lenient="true"/>
复制代码

等价于

<bean id="dateFormat" class="java.text.SimpleDateFormat">
    <constructor-arg value="yyyy-HH-dd HH:mm"/>
    <property name="lenient" value="true"/>
</bean>
复制代码

1.自定义 XML Schema 文件

<!-- myns.xsd (inside package org/springframework/samples/xml) -->
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.mycompany.com/schema/myns"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:beans="http://www.springframework.org/schema/beans"
        targetNamespace="http://www.mycompany.com/schema/myns"
        elementFormDefault="qualified"
        attributeFormDefault="unqualified">

    <xsd:import namespace="http://www.springframework.org/schema/beans"/>

    <xsd:element name="dateformat">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="beans:identifiedType">
                    <xsd:attribute name="lenient" type="xsd:boolean"/>
                    <xsd:attribute name="pattern" type="xsd:string" use="required"/>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>
复制代码

2.自定义NamespaceHandler

NamespacespaceHandler用于解析配置文件时遇到的特定命名空间的所有元素。在我们的例子中,NamespaceHandler应该处理myns:dateformat元素的解析。

NamespaceHandler提供如下三个方法:

  • init(): NamespaceHandler被使用之前调用,完成NamespaceHandler的初始化。
  • BeanDefinition parse(Element, ParserContext): 当遇到顶层元素时被调用。
  • BeanDefinition decorate(Node,BeanDefinitionHandler,ParserContext): 当遇到一个属性或者嵌套元素的时候调用。

Spring提供了一个默认的实现类NamespaceHandlerSupport,我们只需要在init的时候注册每个元素的解析器即可。

public class DateformatNamespaceHandler extends NamespaceHandlerSupport { 

    public void init() { 
        registerBeanDefinitionParser("dateformat", new DeteformatDefinitionParser()); 
    }
}
复制代码

这里实际用到了代理委托的概念,NamespaceHandlerSupport可以注册任意个BeanDefinitionParserNamespaceHandlerSupport负责所有自定义元素的编排,而解析XML的工作委托给各个BeanDefinitionParser负责。

3.自定义BeanDefinitionParser

如果NamespapceHandler遇到元素类型(如:dateformat)已经有对应注册的parser,则DateformatDefinitionParser会被调用,解析相应的属性设置到Bean中。BeanDefinitionParser负责解析一个顶级元素。

Spring提供了AbstractSingleBeanDefinitionParser来处理繁重的解析工作,只需要实现两个方法:

  • Class<?> getBeanClass(Element):返回元素的Class类型。
  • void doParse(Element element,BeanDefinitionBuilder builder):添加元素的属性或者构造参数等等。
ppackage org.springframework.samples.xml;

import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;

import java.text.SimpleDateFormat;

public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

    protected Class getBeanClass(Element element) {
        return SimpleDateFormat.class;
    }

    protected void doParse(Element element, BeanDefinitionBuilder bean) {
        // this will never be null since the schema explicitly requires that a value be supplied
        String pattern = element.getAttribute("pattern");
        bean.addConstructorArg(pattern);

        // this however is an optional property
        String lenient = element.getAttribute("lenient");
        if (StringUtils.hasText(lenient)) {
            bean.addPropertyValue("lenient", Boolean.valueOf(lenient));
        }
    }

}
复制代码

4.注册handler和schema

为了让Spring在解析xml的时候能够感知到我们的自定义元素,我们需要把NamespaceHandlerxsd文件放到2个指定的配置文件中,这2个文件都位于META-INF目录中

  • 'META-INF/spring.handlers':包含XML Schema URI到命名空间处理程序类的映射。因此,对于我们的示例,我们需要编写以下内容:

    http\://www.mycompany.com/schema/myns=org.springframework.samples.xml.DateformatNamespaceHandler
    复制代码
  • META-INF/spring.schemas:包含XML Schema xsd到类路径资源的映射。

    http\://www.mycompany.com/schema/myns/myns.xsd=org/springframework/samples/xml/myns.xsd
    复制代码

5.在Spring XML配置中使用自定义扩展

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:myns="http://www.mycompany.com/schema/myns"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.mycompany.com/schema/myns http://www.mycompany.com/schema/myns/myns.xsd">

    <!-- as a top-level bean -->
    <myns:dateformat id="defaultDateFormat" pattern="yyyy-MM-dd HH:mm" lenient="true"/>

    <bean id="jobDetailTemplate" abstract="true">
        <property name="dateFormat">
            <!-- as an inner bean -->
            <myns:dateformat pattern="HH:mm MM-dd-yyyy"/>
        </property>
    </bean>

</beans>
复制代码

转载于:https://juejin.im/post/5cb1ef136fb9a0689b6ed691

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值