基於Spring可擴展Schema提供自定義配置支持

 

From:http://blog.csdn.net/cutesource/article/details/5864562spring


在不少狀況下,咱們須要爲系統提供可配置化支持,簡單的作法能夠直接基於Spring的標準Bean來配置,但配置較爲複雜或者須要更多豐富控制的時候,會顯得很是笨拙。通常的作法會用原生態的方式去解析定義好的xml文件,而後轉化爲配置對象,這種方式固然能夠解決全部問題,但實現起來比較繁瑣,特別是是在配置很是複雜的時候,解析工做是一個不得不考慮的負擔。Spring提供了可擴展Schema的支持,這是一個不錯的折中方案,完成一個自定義配置通常須要如下步驟:app


設計配置屬性和JavaBeandom

編寫XSD文件ide

編寫NamespaceHandler和BeanDefinitionParser完成解析工做ui

編寫spring.handlers和spring.schemas串聯起全部部件spa

在Bean文件中應用.net

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


1)設計配置屬性和JavaBeancomponent


首先固然得設計好配置項,並經過JavaBean來建模,本例中須要配置People實體,配置屬性name和age(id是默認須要的)orm


public class People {  

    private String id;  

    private String name;  

    private Integer age;  

}  

2)編寫XSD文件


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

  
  
           
  
  
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2.  
  3. <xsd:schema    
  4.  
  5.     xmlns="http://blog.csdn.net/cutesource/schema/people"   
  6.  
  7.     xmlns:xsd="http://www.w3.org/2001/XMLSchema"    
  8.  
  9.     xmlns:beans="http://www.springframework.org/schema/beans"   
  10.  
  11.     targetNamespace="http://blog.csdn.net/cutesource/schema/people"   
  12.  
  13.     elementFormDefault="qualified"    
  14.  
  15.     attributeFormDefault="unqualified">   
  16.  
  17.     <xsd:import namespace="http://www.springframework.org/schema/beans" />   
  18.  
  19.     <xsd:element name="people">   
  20.  
  21.         <xsd:complexType>   
  22.  
  23.             <xsd:complexContent>   
  24.  
  25.                 <xsd:extension base="beans:identifiedType">   
  26.  
  27.                     <xsd:attribute name="name" type="xsd:string" />   
  28.  
  29.                     <xsd:attribute name="age" type="xsd:int" />   
  30.  
  31.                 </xsd:extension>   
  32.  
  33.             </xsd:complexContent>   
  34.  
  35.         </xsd:complexType>   
  36.  
  37.     </xsd:element>   
  38.  
  39. </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目錄下(本例就放在這個目錄下)

【注意】xsd報錯:src-resolve: Cannot resolve the name 'beans:identifiedType' to a(n) 'type definition' component.

 請跳過,這個不影響使用,只是ide的檢查有問題。

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

  
  
           
  
  
  1. import org.springframework.beans.factory.support.BeanDefinitionBuilder;   
  2.  
  3. import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;   
  4.  
  5. import org.springframework.util.StringUtils;   
  6.  
  7. import org.w3c.dom.Element;   
  8.  
  9. public class PeopleBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {   
  10.  
  11.     protected Class getBeanClass(Element element) {   
  12.  
  13.         return People.class;   
  14.  
  15.     }   
  16.  
  17.     protected void doParse(Element element, BeanDefinitionBuilder bean) {   
  18.  
  19.         String name = element.getAttribute("name");   
  20.  
  21.         String age = element.getAttribute("age");   
  22.  
  23.         String id = element.getAttribute("id");   
  24.  
  25.         if (StringUtils.hasText(id)) {   
  26.  
  27.             bean.addPropertyValue("id", id);   
  28.  
  29.         }   
  30.  
  31.         if (StringUtils.hasText(name)) {   
  32.  
  33.             bean.addPropertyValue("name", name);   
  34.  
  35.         }   
  36.  
  37.         if (StringUtils.hasText(age)) {   
  38.  
  39.             bean.addPropertyValue("age", Integer.valueOf(age));   
  40.  
  41.         }   
  42.  
  43.     }   
  44.  
  45. }   

其中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,本例中引用方式以下所示:

<?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: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

相關文章
相關標籤/搜索