要想自定義標籤,首先第一步須要寫本身的XML Schema。XML Schema的我的感受比較複雜,網上的教程比較簡單,所以能夠參照spring-beans.xsd依葫蘆畫瓢。這裏就按照我本身的理解進行簡單介紹一下吧。 ##1.1 最簡單的標籤 一個最簡單的標籤,形式如:node
<bf:head-routing key="1" value="1" to="test2"/>
該標籤只包含了若干屬性,咱們就在xsd文件中這麼定義spring
<!-- 聲明一個標籤,名字爲head-routing,他的類型爲headRouting--> <xsd:element name="head-routing" type="headRouting"></xsd:element> <!-- 定義head-routing的類型,這裏定義它有key,value,to,patten四個屬性 --> <xsd:complexType name="headRouting"> <xsd:attribute name="key" type="xsd:string" use="required"></xsd:attribute> <xsd:attribute name="value" type="xsd:string" use="required"></xsd:attribute> <xsd:attribute name="to" type="xsd:IDREF" use="required"></xsd:attribute> <xsd:attribute name="patten" type="xsd:string" default="string"></xsd:attribute> </xsd:complexType>
在xsd:attribute標籤中的type是用來定義該屬性的格式,例如app
所謂複雜,其實就是嵌套的標籤,形式如:框架
<bf:stop id="test1" ref="testNode"> <bf:head-routing key="1" value="1" to="test2"/> </bf:stop>
其實只要參照Spring 中<bean>標籤的xsd依葫蘆畫瓢,首先是定義stop標籤ide
<xsd:element name="stop"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="beans:identifiedType"> <xsd:group ref="stopElements"/> <xsd:attributeGroup ref="stopAttributes"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element>
其中,函數
<xsd:group name="stopElements"> <xsd:sequence> <xsd:element ref="description" minOccurs="0"/> <xsd:choice minOccurs="0" maxOccurs="unbounded"> <xsd:element ref="head-routing"/> <!-- 有更多的子標籤繼續在這裏添加,例如<xsd:element ref="properties"/> --> </xsd:choice> </xsd:sequence> </xsd:group> <xsd:attributeGroup name="stopAttributes"> <xsd:attribute name="ref" type="xsd:IDREF" use="required"> <xsd:annotation> <xsd:appinfo> <!-- 這裏是使用了Spring tool xsd中的標籤,格式校驗--> <tool:annotation kind="ref"> <tool:expected-type type="com.lizo.node.Station"/> </tool:annotation> </xsd:appinfo> </xsd:annotation> </xsd:attribute> <!-- 有更多的子標籤繼續在這裏添加,例如<xsd:attribute name="value" type="xsd:string"/> -->
完成了xsd文件編寫後,還須要讓該文件生效,就須要在項目的resource/META-INF包裏面配置2個文件spring.handlers和spring.schemasui
改配置文件主要是用一個url來映射咱們第一步配置好的文件,形式以下url
http\://www.lizo.com/schema/bf.xsd=META-INF/bf.xsd
這樣,就能夠在Spring的xml配置文件中加入spring.schemas的url,省略掉其餘的,在<beans>標籤中增長以下信息spa
<beans .. xmlns:bf="http://www.lizo.com/schema/bf" xsi:schemaLocation=" ... http://www.lizo.com/schema/bf http://www.lizo.com/schema/bf.xsd ">
完成這步之後,就能夠在xml中寫本身的標籤了,例如自定義標籤的namespace爲bf,code
<bf:stop id="test123" ref="testNode"> <bf:head-routing key="1" value="1" to="test1"/> <bf:head-routing key="3" value="4" to="test2"/> </bf:stop>
這個配置文件用來配置解析咱們bf標籤,而後生成一些BeanDefinition進行註冊。例如
http\://www.lizo.com/schema/bf=com.lizo.config.BusinessFlowNamespaceHandlerSupport
其中 BusinessFlowNamespaceHandlerSupport就是咱們用來解析標籤
在上一步中,咱們配置了com.lizo.config.BusinessFlowNamespaceHandlerSupport類做爲解析自定義標籤的類,因此namespace爲bf的標籤,都會用這裏註冊的標籤解析器來解析
public class BusinessFlowNamespaceHandlerSupport extends NamespaceHandlerSupport { public void init() { //註冊用於解析<bf:stop>的解析器 registerBeanDefinitionParser("stop", new BusinessFlowBeanDefinitionParser()); } }
咱們自定義的標籤解析器BusinessFlowBeanDefinitionParser是要實現BeanDefinitionParser 接口的
public interface BeanDefinitionParser { BeanDefinition parse(Element element, ParserContext parserContext); }
通常來講,註冊bean的基本流程爲:
解析標籤就不用說,重點說說怎麼生成BeanDefinition
一個最簡單的BeanDefinition經過設置Class和屬性的注入就能夠完成。以下:
RootBeanDefinition nodeWrapDefinition = new RootBeanDefinition(); //該BeanDefinition對應的是什麼類 nodeWrapDefinition.setBeanClass(StationRoutingWrap.class); //name是解析標籤後得到的值 nodeWrapDefinition.getPropertyValues().addPropertyValue("name", name);
RuntimeBeanReference 用於在運行時去獲取BeanDefinition,由於在咱們建立這個BeanDefinition的時候咱們只知道他的beanName,並不肯定是否已經註冊了,這個時候就須要用RuntimeBeanReference,例如
RuntimeBeanReference refBean = new RuntimeBeanReference(ref); nodeWrapDefinition.getPropertyValues().addPropertyValue("station", refBean);
某個BeanDefinition注入的屬性爲一個List,這個時候就須要用ManagedList(同理有ManagedMap,ManagedSet),
ManagedList routingConditions = new ManagedList(); .... nodeWrapDefinition.getPropertyValues().add("routing", routing);
註冊BeanDefinitionParser 接口的函數中有個參數ParserContext,有個方法爲getRegistry(),所以,註冊bean的時候就很簡單了
parserContext.getRegistry().registerBeanDefinition("beanName",nodeWrapDefinition);
經過以上三步,就能夠實現本身定義標籤,而且在Spring容器中注入相關的bean。讓咱們的框架使用起來更方便(更裝B)