• Spring——可扩展的XML Schema机制


    前言

    从Spring2.0开始,Spring提供了XML Schema可扩展机制,用户可以自定义XML Schema文件,并自定义XML Bean解析器,并集成到Spring Ioc 容器中。

    完成XML自定义扩展,需要下面几个步骤:

    • 创建一个 XML Schema 文件,描述自定义的合法构建模块,也就是xsd文件

    • 自定义个处理器类,并实现NamespaceHandler接口

    • 自定义一个或多个解析器,实现BeanDefinitionParser接口

    • 注册NamespaceHandlerSchema

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

    <myns:dateformat id="dateFormat" pattern="yyyy-MM-dd HH:mm" />

    一、自定义 XML Schema 文件

    XML Schema 介绍

    <?xml version="1.0" encoding="UTF-8"?>
    <xsd:schema xmlns="http://www.lh.com/schema/myns" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:beans="http://www.springframework.org/schema/beans" 
        targetNamespace="http://www.lh.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="pattern" type="xsd:string" use="required"/>
                  </xsd:extension>
             </xsd:complexContent>
           </xsd:complexType>
        </xsd:element>
    </xsd:schema>

    其中自定义的命名空间是http://www.lh.com/schema/myns,定义了dateformat元素,属性有pattern

    二、自定义 NamespaceHandler

    定义好XML Schema文件,需要定义一个NamespaceHandler解析配置文件。

    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可以注册任意个BeanDefinitionParser
    NamespaceHandlerSupport负责所有自定义元素的编排,而解析XML的工作委托给各个BeanDefinitionParser负责。
     

    三、自定义BeanDefinitionParser

    BeanDefinitionParser 将被调用,如果NamespapceHandler遇到元素类型已经有对应注册的parser(例如上面的handler如果遇到dateformat,
    DateformatDefinitionParser会被调用,解析相应的属性设置到Bean中)将会被调用。BeanDefinitionParser负责解析一个顶级元素。 
    Spring提供了AbstractSingleBeanDefinitionParser来处理繁重的解析工作,只需要实现两个方法:
    • Class<?> getBeanClass(Element):返回元素的Class类型

    • void doParse(Element element,BeanDefinitionBuilder builder):添加元素的属性或者构造参数等等

    package com.lh.spring;
    
    import org.springframework.beans.factory.support.BeanDefinitionBuilder;
    import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
    import org.w3c.dom.Element;import java.text.SimpleDateFormat;
    
    public class DateformatDefinitionParser extends AbstractSingleBeanDefinitionParser { 
    
        @Override 
        protected Class<?> getBeanClass(Element element) { 
            return SimpleDateFormat.class; 
        } 
    
        @Override
        protected void doParse(Element element, BeanDefinitionBuilder builder) { 
            String pattern = element.getAttribute("pattern"); 
            builder.addConstructorArgValue(pattern); 
        }
    }

    四、注册handler和schema

    为了让Spring在解析xml的时候能够感知到我们的自定义元素,我们需要把namespaceHandlerxsd文件放到2个指定的配置文件中,

    这2个文件都位于META-INF目录中。

    4.1 spring.handlers文件包含了xml schema uriHandler类的映射关系,例如:

    http://www.lh.com/schema/myns=com.lh.spring.DateformatNamespaceHandler

    遇到http://www.lh.com/schema/myns名空间的时候会交给CarNamespaceHandler来处理,key部分必须和xsd文件中的targetNamespace值保持一致

    4.2 spring.schemas文件包含了xml schema xsd文件命名空间和文件路径的映射关系,例如:

    http://www.lh.com/schema/myns.xsd=META-INF/com.lh.date.format/sfm-1.0.xsd

    五、实践测试

    5.1 加入Spring配置文件:

    <?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:my="http://www.lh.com/schema/myns" 
               xsi:schemaLocation=" http://www.springframework.org/schema/beans
                                    http://www.springframework.org/schema/beans/spring-beans.xsd
                                    http://www.lh.com/schema/myns 
                                    http://www.lh.com/schema/myns.xsd"> 
        <my:dateformat id="dateformat" pattern="yyyy-MM-dd HH:mm" />
    </beans>

    5.2 单元测试:

    package com.lh.spring;
    
    import org.junit.Assert;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:spring/application-core.xml"})
    public class XMLSchemaCustomTest { 
    
        @Autowired 
       private SimpleDateFormat dateFormat; @Test public void propertyTest() { Assert.assertNotNull(dateFormat); String date = "2010-10-10 11:12:14"; SimpleDateFormat ymdhms = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { Date time = ymdhms.parse(date); String dateFormatStr = dateFormat.format(time); Assert.assertTrue("2010-10-10 11:12".equals(dateFormatStr)); } catch (ParseException e) { e.printStackTrace(); } } }

    Dubbo XML Schema 扩展实现

    Dubbo 配置:

    我们查看 Dubbo XML Schema 扩展如何实现:

    可以看到 Dubbo XML Schema 扩展刚好对应 Spring 四个标准的步骤。

    引用:
    https://www.jianshu.com/p/8639e5e9fba6
  • 相关阅读:
    android的布局管理器
    android控件---自定义带文本的ImageButton
    新建android项目src和layout文件夹中没有内容的问题
    android控件---spinner
    maven+springMVC+mybatis+junit详细搭建过程 ***
    JUnit4的使用
    Jenkins集成Docker镜像实现自动发布
    Docker部署tomcat及应用
    Docker的离线安装
    Java中的static关键字解析
  • 原文地址:https://www.cnblogs.com/caoweixiong/p/13028159.html
Copyright © 2020-2023  润新知