Spring可扩展的XML Schema机制

可扩展的XML Schema机制

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

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

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

  • 自定义个处理器类,并实现NamespaceHandler接口(比较容易)

  • 自定义一个或多个解析器,实现BeanDefinitionParser接口(最关键的部分)

  • 注册上面的组件到Spring IOC容器中

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


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

可通过这种方式定义SimpleDateFormat

类似


<bean id="dateFormat" class="java.text.SimpleDateFormat"> 

    <constructor-arg value="yyyy-HH-dd HH:mm"/>

</bean>

1.自定义 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

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

3.自定义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); 

    }

}

4.注册handler和schema

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

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


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.实践测试

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(); 

        } 

    }

}

posted @ 2016-10-23 14:38  因为热爱  阅读(443)  评论(0编辑  收藏  举报