Spring系列-XML schema擴充套件機制
原文地址:www.jianshu.com/p/8639e5e9f…
從Spring 2.0版本開始,Spring提供了XML Schema可擴充套件機制,用於定義和配置Bean。完成XML自定義擴充套件,需要下面幾個步驟:
NamespaceHandler BeanDefinitionParser
按照上面的步驟,實現如下可擴充套件XML元素:
<myns:dateformat id="dateFormat" pattern="yyyy-MM-dd HH:mm" lenient="true"/> 複製程式碼
等價於
<bean id="dateFormat" class="java.text.SimpleDateFormat"> <constructor-arg value="yyyy-HH-dd HH:mm"/> <property name="lenient" value="true"/> </bean> 複製程式碼
1.自定義 XML Schema 檔案
<!-- myns.xsd (inside package org/springframework/samples/xml) --> <?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns="http://www.mycompany.com/schema/myns" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" targetNamespace="http://www.mycompany.com/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> 複製程式碼
2.自定義NamespaceHandler
NamespacespaceHandler
用於解析配置檔案時遇到的特定名稱空間的所有元素。在我們的例子中,NamespaceHandler
應該處理myns:dateformat
元素的解析。
NamespaceHandler
提供如下三個方法:
init() BeanDefinition parse(Element, ParserContext) BeanDefinition decorate(Node,BeanDefinitionHandler,ParserContext)
Spring提供了一個預設的實現類NamespaceHandlerSupport
,我們只需要在init的時候註冊每個元素的解析器即可。
public class DateformatNamespaceHandler extends NamespaceHandlerSupport { public void init() { registerBeanDefinitionParser("dateformat", new DeteformatDefinitionParser()); } } 複製程式碼
這裡實際用到了代理委託的概念,NamespaceHandlerSupport
可以註冊任意個BeanDefinitionParser
。NamespaceHandlerSupport
負責所有自定義元素的編排,而解析XML的工作委託給各個BeanDefinitionParser
負責。
3.自定義BeanDefinitionParser
如果NamespapceHandler
遇到元素型別(如:dateformat
)已經有對應註冊的parser,則DateformatDefinitionParser
會被呼叫,解析相應的屬性設定到Bean中。BeanDefinitionParser負責解析一個頂級元素。
Spring提供了AbstractSingleBeanDefinitionParser
來處理繁重的解析工作,只需要實現兩個方法:
Class<?> getBeanClass(Element) void doParse(Element element,BeanDefinitionBuilder builder)
ppackage org.springframework.samples.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; import java.text.SimpleDateFormat; public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected Class getBeanClass(Element element) { return SimpleDateFormat.class; } protected void doParse(Element element, BeanDefinitionBuilder bean) { // this will never be null since the schema explicitly requires that a value be supplied String pattern = element.getAttribute("pattern"); bean.addConstructorArg(pattern); // this however is an optional property String lenient = element.getAttribute("lenient"); if (StringUtils.hasText(lenient)) { bean.addPropertyValue("lenient", Boolean.valueOf(lenient)); } } } 複製程式碼
4.註冊handler和schema
為了讓Spring在解析xml的時候能夠感知到我們的自定義元素,我們需要把NamespaceHandler
和xsd檔案
放到2個指定的配置檔案中,這2個檔案都位於META-INF
目錄中
-
'META-INF/spring.handlers'
:包含XML Schema URI到名稱空間處理程式類的對映。因此,對於我們的示例,我們需要編寫以下內容:http\://www.mycompany.com/schema/myns=org.springframework.samples.xml.DateformatNamespaceHandler 複製程式碼
-
META-INF/spring.schemas
:包含XML Schema xsd到類路徑資源的對映。http\://www.mycompany.com/schema/myns/myns.xsd=org/springframework/samples/xml/myns.xsd 複製程式碼
5.在Spring 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:myns="http://www.mycompany.com/schema/myns" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.mycompany.com/schema/myns http://www.mycompany.com/schema/myns/myns.xsd"> <!-- as a top-level bean --> <myns:dateformat id="defaultDateFormat" pattern="yyyy-MM-dd HH:mm" lenient="true"/> <bean id="jobDetailTemplate" abstract="true"> <property name="dateFormat"> <!-- as an inner bean --> <myns:dateformat pattern="HH:mm MM-dd-yyyy"/> </property> </bean> </beans> 複製程式碼