spring xml扩展

来源:互联网 发布:网络面板cad表示 编辑:程序博客网 时间:2024/06/05 07:22
         从Spring 2.0版本开始支持扩展XML配置,开发人员可以扩展xml配置,根据bean的定义元素标签就能够看出改bean的作用,使组件的配置更加直观、易阅读。

扩展XML配置大致需要一下几个步骤
1、定义一个xsd文件描述组件内容
2、创建一个bean 定义解析器,实现BeanDefinitionParser接口,用来解析xsd文件中描述的元素。
3、创建一个名称空间解析器,实现NamespaceHandler接口,一般都是扩展NamespaceHandlerSupport类,作用是将组件注册到Spring容器
4、编写spring.handlers和spring.schemas文件,即注册处理器和方案。

 

首先编写xsd文件:


<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.springframework.org/schema/myns"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:beans="http://www.springframework.org/schema/beans"
    targetNamespace="http://www.springframework.org/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>


      上面的xsd文件描述了一个新的targetNamespace,并在这个空间中定义了一个name为dateformat的element,改元素有两个属性lenient和pattern。

 

      编写bean定义解析器,实现了BeanDefinitionParser接口,用来解析xsd文件中定义的元素并注册到spring 容器中。


package com.springinaction.xmlextension;

import java.text.SimpleDateFormat;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;

public class SimpleDateFormatBeanDefinitionParser implements BeanDefinitionParser {
   
    public BeanDefinition parse(Element element, ParserContext parserContext) {
             
       RootBeanDefinition beanDef = new RootBeanDefinition();
       beanDef.setBeanClass(SimpleDateFormat.class);     
       String pattern = element.getAttribute("pattern");
       beanDef.getConstructorArgumentValues().addGenericArgumentValue(pattern);

//这是因为pattern属性是构造函数中的一个参数,所以需要调用

//getConstructorArgumentValues()方法,而不是和lenient属性一样处理

       String lenientString = element.getAttribute("lenient");
       if (StringUtils.hasText(lenientString)) {
                           beanDef.getPropertyValues().addPropertyValue("lenient", new Boolean(lenientString));
       }
     
       String id = element.getAttribute("id");
      
            BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDef, id);
      //注册bean定义到spring 容器中,此处也可不注册,spring 容器会帮助我们自//动注册
       BeanDefinitionReaderUtils.registerBeanDefinition(holder, parserContext.getRegistry());
      
       return beanDef;
    }
 }


注意,id属性是一个默认的属性,可以不在xsd文件中描述,但是需要注册它,否则将无法通过getBean方法获取标签定义的bean,也无法被其他bean引用。


      编写名称空间解析器,扩展自NamespaceHandlerSupport,它的作用是将组件注册到Spring容器,我们一般只需要在它的init()方法中注册bean定义解析器,不需要做其它的。


package com.springinaction.xmlextension;

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

public class MyNamespaceHandler extends NamespaceHandlerSupport {
   
    public void init() {
        registerBeanDefinitionParser("dateformat",
                new SimpleDateFormatBeanDefinitionParser());       
    }
   
}

 

 

编写spring.handlers:
http\://www.springframework.org/schema/myns=com.springinaction.xmlextension.MyNamespaceHandler

编写spring.schemas:
http\://www.springframework.org/schema/myns/myns.xsd=com/springinaction/xmlextension/myns.xsd

spring.schemas将告诉Spring 扩展的xsd文件存放在什么位置。
而spring.handlers文件将告诉Spring,schema和handler的映射关系,某个schema应该有哪个handler来处理。

 

配置文件和测试类:
<?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.springframework.org/schema/myns"
 xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd
 http://www.springframework.org/schema/mynshttp://www.springframework.org/schema/myns/myns.xsd">

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


package com.springinaction.xmlextension;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class Test {
 public static void main(String[] args) {
  BeanFactory bf = new XmlBeanFactory(
         new ClassPathResource("com/springinaction/xmlextension/extension.xml"));
  SimpleDateFormat sdf = (SimpleDateFormat)bf.getBean("dateFormat");
  System.out.println(sdf.format(new Date()));
 }
}


运行测试类,将会按照配置文件中指定的格式打印输出当前时间。

原创粉丝点击