Spring2.0 xml schema功能-允許在spring配置文件中添加自己的xml schema及解析器

轉自:http://www.cnblogs.com/jifeng/archive/2011/09/14/2176599.html

在很多情況下,我們需要爲系統提供可配置化支持,簡單的做法可以直接基於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如下:

複製代碼
<?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> 
複製代碼

 

關於xsd:schema的各個屬性具體含義就不作過多解釋,可以參見http://www.w3school.com.cn/schema/schema_schema.asp

<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就是本例中的解析類:

 

複製代碼
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));  
        }  
    }  
}  
複製代碼

 

其中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

以上表示當使用到名爲"http://blog.csdn.net/cutesource/schema/people"的schema引用時,會通過study.schemaExt.MyNamespaceHandler來完成解析

spring.schemas如下所示:

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

以上就是載入xsd文件

5)在Bean文件中應用

到此爲止一個簡單的自定義配置以完成,可以在具體應用中使用了。使用方法很簡單,和配置一個普通的spring bean類似,只不過需要基於我們自定義schema,本例中引用方式如下所示:

 

複製代碼
<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> 
複製代碼

 

其中xmlns:cutesource="http://blog.csdn.net/cutesource/schema/people"是用來指定自定義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提供自定義配置支持實戰過程,一些複雜應用和技巧還有待挖掘

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章