频道栏目
首页 > 资讯 > 其他 > 正文

spring schema 扩展(NamespaceHandler,BeanDefinitionParser)

17-08-10        来源:[db:作者]  
收藏   我要投稿

前言:Spring从2.0开始引入了一个新的机制用于扩展xml模式,我们就可以编写自定义的xml bean解析器然后集成到Spring IoC容器中(Spring不识别aop,mvc,这些标签都是通过本章要学习的内容,扩展标签)

<mvc:interceptors>mvc:interceptors>

<aop:config>aop:config>

 

xml扩展大概有以下几个步骤:

  • 编写自定义类
  • 编写xml schema来描述自定义元素
  • 编写NamespaceHandler实现类
  • 编写BeanDefinitionParser实现类
  • 把以上组建注册到Spring

    xml的schema约束:

    先来说说xml文档的schema约束,它定义了xml文档的结构,内容和语法,包括元素和属性、关系的结构以及数据类型等等。有以下几点需要遵循:

    1) 、所有的标签和属性都需要Schema来定义。(schema本身由w3c来定义)。

    2)、所有的schema文件都需要以个ID,这里我们称之为 namespace,其值时一个url,通常是这个xml的xsd文件的地址。

    3)、namespace值由 targetNamespace属性来指定

    4)、引入一个schema约束,使用属性xmlns,属性值即为对应schema文件的命名空间 nameSpace。

    5)、如果引入的schema非w3c组织定义的,必须指定schema文件的位置,schema文件的位置由 schemaLocation来指定。

    6)、引入多个schema文件需要使用 别名。别名形式如下: xmlns:alias。

    对于上述配置文件的详细解读:

    1)、声明默认的名称空间(xmlns="http://www.springframework.org/schema/beans")

    2)、 声明XML Schema实例名称空间(http://www.w3.org/2001/XMLSchema-instance),并将xsi前缀与该名称空间绑定, 这样模式处理器就可以识别xsi:schemaLocation属性。XML Schema实例名称空间的前缀通常使用xsi

    3)、使 用xsi:schemaLocation属性指定名称空间(http://www.springframework.org/schema/beans) 和模式位置(http://www.springframework.org/schema/beans/spring-beans.xsd)相关。 XML Schema推荐标准中指出,xsi:schemaLocation属性可以在实例中的任何元素上使用,而不一定是根元素,不 过,xsi:schemaLocation属性必须出现在它要验证的任何元素和属性之前。

    4)、使用别名引入多个schema文件。如上述 xmlns:mvc 、xmlns:tx 、xmlns:context等等。

    编写自定义类

    public class Miku {
    
       private String name;
       private int age;
       private char sex;
    }

    编写自定义schema,文件名为:miku.xsd,路径为:classpath:META-INF/my.xsd

    xml version="1.0" encoding="UTF-8"?>
    <xsd:schema xmlns="http://www.mycompany.com/schema/my"
             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
             xmlns:beans="http://www.springframework.org/schema/beans"
             targetNamespace="http://www.mycompany.com/schema/my"
             elementFormDefault="qualified"
             attributeFormDefault="unqualified">
    
    <xsd:import namespace="http://www.springframework.org/schema/beans"/>
    
    <xsd:element name="miku">
       <xsd:complexType>
          <xsd:complexContent>
             <xsd:extension base="beans:identifiedType">
                <xsd:attribute name="name" type="xsd:string" use="required"/>
                <xsd:attribute name="age" type="xsd:int"/>
                <xsd:attribute name="sex" type="xsd:char"/>
             xsd:extension>
          xsd:complexContent>
       xsd:complexType>
    xsd:element>
    xsd:schema>
     
     
    然后我们就可以像这样定义miku:

    编写NamespaceHandler

    NamespaceHandler用于解析我们自定义名字空间下的所有元素,目前我们要解析上面的my:miku元素。NamespaceHandler里面只有3个方法:

    • init()会在NamespaceHandler初始化的时候被调用。
    • BeanDefinition parse(Element, ParserContext)- 当Spring遇到一个顶层元素的时候被调用。
    • BeanDefinitionHolder decorate(Node, BeanDefinitionHolder, ParserContext)- 当Spring遇到一个属性或嵌套元素的时候调用.

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

       

      public class MikuNamespaceHandler extends NamespaceHandlerSupport {
      
         @Override
         public void init() {
            //遇到miku元素的时候交给MikuBeanDefinitionParser来解析
            registerBeanDefinitionParser("miku", new MikuBeanDefinitionParser());
         }
      }

       

      编写BeanDefinitionParser

      当遇到miku元素时,Spring会交给MikuBeanDefinitionParser来解析。MikuBeanDefinitionParser取出相应的属性然后设置到bean中。

       

      public class MikuBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
      
         @Override
         protected Class getBeanClass(Element element) {
            //miku元素对应Miku对象类型
            return Miku.class;
         }
      
         @Override
         protected void doParse(Element element, BeanDefinitionBuilder builder) {
      
            String name = element.getAttribute("name");
            String age = element.getAttribute("age");
            String sex = element.getAttribute("sex");
      
            //把对应的属性设置到bean中
            if(StringUtils.hasText(name))
               builder.addPropertyValue("name", name);
      
            if(StringUtils.hasText(age))
               builder.addPropertyValue("age", age);
      
            if(StringUtils.hasText(sex))
               builder.addPropertyValue("sex", sex);
      
         }
      }

       

      注册handler和schema(将组件串联起来)

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

    META-INF/spring.handlers

    spring.handlers文件包含了xml schema uri和handler类的映射关系,比如:

    http\://www.mycompany.com/schema/my=spring.xml.ext.schema.MikuNamespaceHandler

    这表示遇到http\://www.mycompany.com/schema/my命名空间的时候会交给MikuNamespaceHandler来处理。

    注意上面的冒号转义。 key部分必须和xsd文件中的targetNamespace值保持一致。


相关TAG标签
上一篇:CSS3新特性(二)选择器
下一篇:C/C++学习笔记七(内存管理)
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站