你一定的收藏的Dubbo設計模式解析:對Spring配置標籤擴展

一、dubbo是如何“插入”到spring框架中的

dubbo是基於Spring進行開發的,而且擴展了Spring的XML schema和註解標籤,其實這裏也就是整個dubbo的切入點。dubbo除去依賴其他的第三方框架外,整個框架只有一個jar包,可謂是精緻。在這個jar包的NET-INF目錄下有兩個文件:spring.handlers和spring.schemas。其中spring.schemas中定義的就是擴展的spring配置標籤,而且spring.handlers中定義的就是這些schema的處理類,就是這個類將dubbo組件“插入”到spring這個平臺裏的。(關於如何自定義spring配置的schema,網上資料很多,這裏只簡單概括)Spring在啓動的時候會掃描MET-INF下所有的spring.handlers等文件,找到其中的標籤處理類,並運行其init方法。

這裏要插個知識點“spring的啓動過程”。spring啓動過程,從宏觀角度來講分爲兩個階段。第一個階段完成spring配置文件的解析,或者spring註解的解析最終將這些配置或者註解解析成BeanDefinition對象,然後進入下一個階段,比如我們經常在spring配置文件中使用的佔位符替換工作就是在這個階段完成的。在第二個階段中,spring用之前解析好的BeanDefinition對象來完成bean的初始化和組裝工作,比如我們使用spring事務時的事務proxy就是這個階段完成注入到service對象中的。

在這個init方法中,dubbo將自己的標籤(application,module,registry,monitor,provider,consumer,protocol,service,reference)處理類註冊到spring中,而這些類會完成對自己所負責的標籤的解析工作,將標籤最終轉換爲bean的描述對象BeanDefinition並返回給spring,而spring拿到這些標籤對象完成bean的初始化、依賴注入(比如注入對RMI端的proxy對象)。

二、Dubbo中對Spring配置標籤擴展

你一定的收藏的Dubbo設計模式解析:對Spring配置標籤擴展

Java

Spring提供了可擴展Schema的支持,完成一個自定義配置一般需要以下步驟:

  • 設計配置屬性和JavaBean

  • 編寫XSD文件

  • 編寫NamespaceHandler和BeanDefinitionParser完成解析工作

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

  • 在Bean文件中應用

dubbo中所有dubbo的標籤,都統一用DubboBeanDefinitionParser進行解析,基於一對一屬性映射,將XML標籤解析爲Bean對象。

下面我們就用dubbo爲例來看如何實現對Spring配置的標籤擴展。

2.1、設計配置屬性和JavaBean

我們首先當然得設計好配置項,並通過JavaBean來建模。

以Dubbo的ServiceBean爲例,這裏定義的了dubbo每個服務的信息。

你一定的收藏的Dubbo設計模式解析:對Spring配置標籤擴展

Java

2.2、編寫XSD文件

XSD文件所在的位置在dubbo-config-spring項目中,如下圖:

你一定的收藏的Dubbo設計模式解析:對Spring配置標籤擴展

Java

以後面要用到的dubbo:service爲例,:

<xsd:element name="service" type="serviceType">

<xsd:annotation>

<xsd:documentation><![CDATA[ Export service config ]]></xsd:documentation>

</xsd:annotation>

</xsd:element>

serviceType類型的定義如下:

<xsd:complexType name="serviceType">

<xsd:complexContent>

<xsd:extension base="abstractServiceType">

<xsd:choice minOccurs="0" maxOccurs="unbounded">

<xsd:element ref="method" minOccurs="0" maxOccurs="unbounded" />

<xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded" />

<xsd:element ref="beans:property" minOccurs="0" maxOccurs="unbounded" />

</xsd:choice>

<xsd:attribute name="interface" type="xsd:token" use="required">

<xsd:annotation>

<xsd:documentation></xsd:documentation>

<xsd:appinfo>

<tool:annotation>

<tool:expected-type type="java.lang.Class"/>

</tool:annotation>

</xsd:appinfo>

</xsd:annotation>

</xsd:attribute>

<xsd:attribute name="ref" type="xsd:string" use="optional">

<xsd:annotation>

<xsd:documentation></xsd:documentation>

</xsd:annotation>

</xsd:attribute>

<xsd:attribute name="class" type="xsd:string" use="optional">

<xsd:annotation>

<xsd:documentation><![CDATA[ The service implementation class name. ]]></xsd:documentation>

</xsd:annotation>

</xsd:attribute>

<xsd:attribute name="path" type="xsd:string" use="optional">

<xsd:annotation>

<xsd:documentation><![CDATA[ The service path. ]]></xsd:documentation>

</xsd:annotation>

</xsd:attribute>

<xsd:attribute name="provider" type="xsd:string" use="optional">

<xsd:annotation>

<xsd:documentation><![CDATA[ Deprecated. Replace to protocol. ]]></xsd:documentation>

</xsd:annotation>

</xsd:attribute>

<xsd:attribute name="generic" type="xsd:string" use="optional">

<xsd:annotation>

<xsd:documentation><![CDATA[ Generic service. ]]></xsd:documentation>

</xsd:annotation>

</xsd:attribute>

<xsd:anyAttribute namespace="##other" processContents="lax" />

</xsd:extension>

</xsd:complexContent>

</xsd:complexType>

比如其中的 <xsd:attribute name="ref" type="xsd:string" use="optional"> 對應的 string類型的配置項 ref。

你一定的收藏的Dubbo設計模式解析:對Spring配置標籤擴展

Java

2.3、編寫NamespaceHandler和BeanDefinitionParser完成解析工作

要完成解析工作,會用到NamespaceHandler和BeanDefinitionParser這兩個概念。具體說來NamespaceHandler會根據schema和節點名找到某個BeanDefinitionParser,然後由BeanDefinitionParser完成具體的解析工作。因此需要分別完成NamespaceHandler和BeanDefinitionParser的實現類,Spring提供了默認實現類NamespaceHandlerSupport和AbstractSingleBeanDefinitionParser,簡單的方式就是去繼承這兩個類。

如上圖,dubbo的 NamespaceHandler 文件在 com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler 。

Handler 定義了每個配置節解析的對象,如下圖代碼。

DubboBeanDefinitionParser 定義也在這個目錄下。

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

上面幾個步驟走下來會發現開發好的handler與xsd還沒法讓應用感知到,就這樣放上去是沒法把前面做的工作納入體系中的,spring提供了spring.handlers和spring.schemas這兩個配置文件來完成這項工作,這兩個文件需要我們自己編寫並放入META-INF文件夾中,這兩個文件的地址必須是META-INF/spring.handlers和META-INF/spring.schemas,spring會默認去載入它們。

這兩個文件,在dubbo項目中,是在dubbo-config-spring項目中,如下圖:

spring.handlers 文件的內容如下:

http://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

以上表示當使用到名爲"http://code.alibabatech.com/schema/dubbo"的schema引用時,會通過com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler 來完成解析

spring.schemas 文件的內容如下:

http://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd

以上標示載入的xsd文件的位置。

你一定的收藏的Dubbo設計模式解析:對Spring配置標籤擴展

Java

2.5、在Bean文件中應用

Dubbo的Spring的配置文件來自哪裏,請參考這篇文章:

Dubbo 通過Spring 配置具體啓動服務:

以dubbo-demo-provider爲例,它的Spring配置文件 dubbo-demo-provider.xml內容如下:

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

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

xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"

xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd">

<bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl" />

<dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" />

</beans>

你一定的收藏的Dubbo設計模式解析:對Spring配置標籤擴展

Java

其中:

  • xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" 是用來指定自定義schema,

  • xsi:schemaLocation用來指定xsd文件。

  • <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService" /> 是一個具體的自定義配置使用實例。

  • Java學習資料獲取(複製下段連接至瀏覽器即可)
    data:text/html;charset=UTF-8;base64,5oGt5Zac5L2g77yM5p625p6E5biI5a2m5Lmg576k5Y+35pivNjg2NTc5MDE0Cg==

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