天天看點

spring源碼學習之:xml标簽擴充配置例子

在很多情況下,我們需要為系統提供可配置化支援,簡單的做法可以直接基于Spring的标準Bean來配置,但配置較為複雜或者需要更多豐富控制的 時候,會顯得非常笨拙。一般的做法會用原生态的方式去解析定義好的xml檔案,然後轉化為配置對象,這種方式當然可以解決所有問題,但實作起來比較繁瑣, 特别是是在配置非常複雜的時候,解析工作是一個不得不考慮的負擔。Spring提供了可擴充Schema的支援,這是一個不錯的折中方案,完成一個自定義 配置一般需要以下步驟:

設計配置屬性和JavaBean

編寫XSD檔案

編寫NamespaceHandler和BeanDefinitionParser完成解析工作

編寫spring.handlers和spring.schemas串聯起所有部件

在Bean檔案中應用

下面結合一個小例子來實戰以上過程

1)設計配置屬性和JavaBean

首先當然得設計好配置項,并通過JavaBean來模組化,本例中需要配置People實體,配置屬性name和age(id是預設需要的)

public class People {  

    private String id;  

    private String name;  

    private Integer age;  

}  

2)編寫XSD檔案

為上一步設計好的配置項編寫XSD檔案,XSD是schema的定義檔案,配置的輸入和解析輸出都是以XSD為契約,本例中XSD如下:

spring源碼學習之:xml标簽擴充配置例子

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

<xsd:schema   

    xmlns="http://blog.csdn.net/cutesource/schema/people"  

    xmlns:xsd="http://www.w3.org/2001/XMLSchema"   

    xmlns:beans="http://www.springframework.org/schema/beans"  

    targetNamespace="http://blog.csdn.net/cutesource/schema/people"  

    elementFormDefault="qualified"   

    attributeFormDefault="unqualified">  

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

    <xsd:element name="people">  

        <xsd:complexType>  

            <xsd:complexContent>  

                <xsd:extension base="beans:identifiedType">  

                    <xsd:attribute name="name" type="xsd:string" />  

                    <xsd:attribute name="age" type="xsd:int" />  

                </xsd:extension>  

            </xsd:complexContent>  

        </xsd:complexType>  

    </xsd:element>  

</xsd:schema> 

spring源碼學習之:xml标簽擴充配置例子

<xsd:element

name="people">對應着配置項節點的名稱,是以在應用中會用people作為節點名來引用這個配置

<xsd:attribute name="name" type="xsd:string"

/>和<xsd:attribute name="age"

type="xsd:int"

/>對應着配置項people的兩個屬性名,是以在應用中可以配置name和age兩個屬性,分别是string和int類型

完成後需把xsd存放在classpath下,一般都放在META-INF目錄下(本例就放在這個目錄下)

3)編寫NamespaceHandler和BeanDefinitionParser完成解析工作

下面需要完成解析工作,會用到NamespaceHandler和BeanDefinitionParser這兩個概念。具體說來

NamespaceHandler會根據schema和節點名找到某個BeanDefinitionParser,然後由

BeanDefinitionParser完成具體的解析工作。是以需要分别完成NamespaceHandler和

BeanDefinitionParser的實作類,Spring提供了預設實作類NamespaceHandlerSupport和

AbstractSingleBeanDefinitionParser,簡單的方式就是去繼承這兩個類。本例就是采取這種方式:

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

public class MyNamespaceHandler extends NamespaceHandlerSupport {  

    public void init() {  

        registerBeanDefinitionParser("people", new PeopleBeanDefinitionParser());  

    }  

其中registerBeanDefinitionParser("people", new

PeopleBeanDefinitionParser());就是用來把節點名和解析類聯系起來,在配置中引用people配置項時,就會用

PeopleBeanDefinitionParser來解析配置。PeopleBeanDefinitionParser就是本例中的解析類:

spring源碼學習之:xml标簽擴充配置例子

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 PeopleBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {  

    protected Class getBeanClass(Element element) {  

        return People.class;  

    protected void doParse(Element element, BeanDefinitionBuilder bean) {  

        String name = element.getAttribute("name");  

        String age = element.getAttribute("age");  

        String id = element.getAttribute("id");  

        if (StringUtils.hasText(id)) {  

            bean.addPropertyValue("id", id);  

        }  

        if (StringUtils.hasText(name)) {  

            bean.addPropertyValue("name", name);  

        if (StringUtils.hasText(age)) {  

            bean.addPropertyValue("age", Integer.valueOf(age));  

spring源碼學習之:xml标簽擴充配置例子

其中element.getAttribute就是用配置中取得屬性值,bean.addPropertyValue就是把屬性值放到bean中。

4)編寫spring.handlers和spring.schemas串聯起所有部件

上面幾個步驟走下來會發現開發好的handler與xsd還沒法讓應用感覺到,就這樣放上去是沒法把前面做的工作納入體系中的,spring提供了

spring.handlers和spring.schemas這兩個配置檔案來完成這項工作,這兩個檔案需要我們自己編寫并放入META-INF檔案夾

中,這兩個檔案的位址必須是META-INF/spring.handlers和META-INF/spring.schemas,spring會預設去

載入它們,本例中spring.handlers如下所示:

http\://blog.csdn.net/cutesource/schema/people=study.schemaExt.MyNamespaceHandler

spring.schemas如下所示:

http\://blog.csdn.net/cutesource/schema/people.xsd=META-INF/people.xsd

以上就是載入xsd檔案

5)在Bean檔案中應用

到此為止一個簡單的自定義配置以完成,可以在具體應用中使用了。使用方法很簡單,和配置一個普通的spring

bean類似,隻不過需要基于我們自定義schema,本例中引用方式如下所示:

spring源碼學習之:xml标簽擴充配置例子

<beans xmlns="http://www.springframework.org/schema/beans"  

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   

    xmlns:cutesource="http://blog.csdn.net/cutesource/schema/people"  

    xsi:schemaLocation="  

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  

http://blog.csdn.net/cutesource/schema/people http://blog.csdn.net/cutesource/schema/people.xsd">  

    <cutesource:people id="cutesource" name="袁志俊" age="27"/>  

</beans> 

spring源碼學習之:xml标簽擴充配置例子

是用來指定自定義schema,xsi:schemaLocation用來指定xsd檔案。<cutesource:people

id="cutesource" name="zhijun.yuanzj"

age="27"/>是一個具體的自定義配置使用執行個體。

最後就可以在具體程式中使用基本的bean載入方式來載入我們的自定義配置對象了,如:

ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");  

People p = (People)ctx.getBean("cutesource");  

System.out.println(p.getId());  

System.out.println(p.getName());  

System.out.println(p.getAge());  

會輸出:

cutesource

袁志俊

27

以上就是一個基于Spring可擴充Schema提供自定義配置支援實戰過程,一些複雜應用和技巧還有待挖掘