Spring之自定义Schema

概述

可以通过扩展Spring的Schema,来实现自定义配置。完成一个自定义配置一般需要完成下面的步骤:

  • 设计属性并编写JavaBean
  • 编写xsd
  • 编写NamespaceHandler类和BeanDefinitionParser类
  • 编写spring.schemas和spring.handlers串联所有的组件
  • 在Bean配置文件中使用

下面是我测试的项目结构: 1111


编写JavaBean

person.java
package cn.timd.spring.spring_schema;

public class Person {  
    private String id;  //id默认是需要的
    private String name;
    private Integer age;

    public Person() {
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

编写xsd文件

person.xsd
<?xml version="1.0" encoding="UTF-8" ?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
    xmlns="http://timd.cn/schema/person"
    targetNamespace="http://timd.cn/schema/person"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"
    elementFormDefault="qualified"
    attributeFormDefault="unqualified">

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

    <xsd:element name="person">
        <xsd:complexType>
            <xsd:complexContent>
                <xsd:extension base="beans:identifiedType">
                    <xsd:attribute name="name" type="xsd:string"></xsd:attribute>
                    <xsd:attribute name="age" type="xsd:int"></xsd:attribute>
                </xsd:extension>
            </xsd:complexContent>
        </xsd:complexType>
    </xsd:element>

</xsd:schema>  


关于xsd的详细信息,可查看:http://www.w3school.com.cn/schema/index.asp。 完成后,需要把xsd放到CLASSPATH下,一般都放在META-INF目录下。


编写NamespaceHandler类和BeanDefinitionParser类

NamespaceHandler类负责根据schema和节点找到相应的BeanDefinitionParser,然后由BeanDefinitionParser完成具体的解析工作。
因此需要分别完成NamespaceHandler和BeanDefinitionParser的实现类,Spring提供了默认实现类NamespaceHandlerSupport和AbstractSingleBeanDefinitionParser,简单的方式就是去继承这两个类。

PersonNamespaceHandler.java
package cn.timd.spring.spring_schema;

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

public class PersonNamespaceHandler extends NamespaceHandlerSupport {  
    public void init(){
        registerBeanDefinitionParser("person", new PersonBeanDefinitionParser());
    }
}


registerBeanDefinitionParser用来把节点名和解析类关联起来

PersonBeanDefinitionParser.java
package cn.timd.spring.spring_schema;

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

public class PersonBeanDefinitionParser extends AbstractSingleBeanDefinitionParser  {

    protected Class<?> getBeanClass(Element element) {
        return Person.class;
    }

    protected void doParse(Element ele, BeanDefinitionBuilder bean) {
        String id = ele.getAttribute("id");
        String name = ele.getAttribute("name");
        String age = ele.getAttribute("age");

        if (StringUtils.hasText(id))
            bean.addPropertyValue("id", Integer.valueOf(id));
        if (StringUtils.hasText(name))
            bean.addPropertyValue("name", name);
        if (StringUtils.hasText(age))
            bean.addPropertyValue("age", Integer.valueOf(age));
    }
}


ele.getAttribute用于从配置中取得属性值,bean.addPropertyValue用于把属性值放到bean中

编写spring.handlers和spring.schemas

spring.handlers和spring.schemas用于串联所有的组件---xsd文件、NamespaceHandler类以及BeanDefinitionParser类。这两个文件必须放在META-INF下(xsd文件可以放在META-INF下,也可以放在类路径下)。

  • spring.handlers - 用于指定namespaceURI 和 NamespaceHandler类之间的映射
http\://timd.cn/schema/person=cn.timd.spring.spring_schema.PersonNamespaceHandler  
  • spring.schemas - 用于从本地加载xsd
http\://timd.cn/schema/person/person.xsd=META-INF/person.xsd  

在Bean配置文件中使用

applicationContext.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:person="http://timd.cn/schema/person"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
       http://timd.cn/schema/person
       http://timd.cn/schema/person/person.xsd">

    <person:person name="timchow" age="28" id="10086"></person:person>

</beans>  
Main.java
package cn.timd.spring.spring_schema;

import org.springframework.context.ApplicationContext;  
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {  
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = (Person) ctx.getBean("10086");
        System.out.println(person);
    }
}

感谢浏览tim chow的作品!

如果您喜欢,可以分享到: 更多

如果您有任何疑问或想要与tim chow进行交流

可点此给tim chow发信

如有问题,也可在下面留言: