閱讀766 返回首頁    go 阿裏雲 go 技術社區[雲棲]


分布式服務Dubbo從入門到"精通"之Schema實現

前言

盡管使用了Dubbo許久,但其實對於其了解還是九牛一毛,上個月通讀了Netty實戰(粗略的了解),突然有了解讀Dubbo源碼的欲望,時不待我,那就趕緊開始吧。

熟悉Dubbo的朋友,可能都知道其采用全Spring配置方式,透明化接入應用,對應用沒有任何API侵入,隻需用Spring加載Dubbo的配置即可,Dubbo基於Spring的Schema擴展進行加載。

當然,如果你不想使用Spring配置,而希望通過API的方式進行調用,Dubbo也是支持的,但是官方是不推薦的(原因你猜)。

今天,就跟大家聊一聊Dubbo是如何基於Schema實現的。

準備

1121698433

具體實現,需要使用到一下幾個配置或者是類:
spring.handlers:解析所使用的類
spring.schemas:自定義標簽的路徑
DubboNamespaceHandler.java:處理器
DubboBeanDefinitionParser.java:解析器
xxxxConfig.java:JavaBean建模

實現

這裏我們以dubbo:application做案例介紹

實體類ApplicationConfig.java

位於com.alibaba.dubbo.config包下,截取部分代碼:

public class ApplicationConfig extends AbstractConfig {
    private static final long serialVersionUID = 5508512956753757169L;
    private String name;
    private String version;
    private String owner;
    private String organization;
    private String architecture;
    private String environment;
    private String compiler;
    private String logger;
    private List<RegistryConfig> registries;
    private MonitorConfig monitor;
    private Boolean isDefault;

    public ApplicationConfig() {
    }

    public ApplicationConfig(String name) {
        setName(name);
    }

編寫dubbo.xsd文件

位於META-INF下,截取部分代碼:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="https://code.alibabatech.com/schema/dubbo"
    xmlns:xsd="https://www.w3.org/2001/XMLSchema" 
    xmlns:beans="https://www.springframework.org/schema/beans"
    xmlns:tool="https://www.springframework.org/schema/tool"
    targetNamespace="https://code.alibabatech.com/schema/dubbo">

    <xsd:import namespace="https://www.w3.org/XML/1998/namespace"/>
    <xsd:import namespace="https://www.springframework.org/schema/beans"/>
    <xsd:import namespace="https://www.springframework.org/schema/tool"/>

    <xsd:annotation>
        <xsd:documentation><![CDATA[ Namespace support for the dubbo services provided by dubbo framework. ]]></xsd:documentation>
    </xsd:annotation>

    <xsd:complexType name="applicationType">
        <xsd:attribute name="id" type="xsd:ID">
            <xsd:annotation>
                <xsd:documentation><![CDATA[ The unique identifier for a bean. ]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="name" type="xsd:string" use="required">
            <xsd:annotation>
                <xsd:documentation><![CDATA[ The application name. ]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="version" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[ The application version. ]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="owner" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[ The application owner name (email prefix). ]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="organization" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[ The organization name. ]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="architecture" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[ The architecture. ]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="environment" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[ The application environment, eg: dev/test/run ]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="compiler" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[ The java code compiler. ]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="logger" type="xsd:string">
            <xsd:annotation>
                <xsd:documentation><![CDATA[ The application logger. ]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="registry" type="xsd:string" use="optional">
            <xsd:annotation>
                <xsd:documentation><![CDATA[ The application registry. ]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="monitor" type="xsd:string" use="optional">
            <xsd:annotation>
                <xsd:documentation><![CDATA[ The application monitor. ]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
        <xsd:attribute name="default" type="xsd:string" use="optional">
            <xsd:annotation>
                <xsd:documentation><![CDATA[ Is default. ]]></xsd:documentation>
            </xsd:annotation>
        </xsd:attribute>
    </xsd:complexType>

    <xsd:element name="annotation" type="annotationType">
        <xsd:annotation> 
            <xsd:documentation><![CDATA[ The annotation config ]]></xsd:documentation> 
        </xsd:annotation>
    </xsd:element>
</xsd:schema>

關於xsd:schema的各個屬性具體含義就不作過多陳述,大家可以參見

https://www.w3school.com.cn/schema/schema_elements_ref.asp

DubboBeanDefinitionParser和DubboNamespaceHandler實現解析

DubboNamespaceHandler會根據schema和節點名找到某個DubboBeanDefinitionParser,然後由DubboBeanDefinitionParser完成具體的解析工作。因此需要分別繼承NamespaceHandlerSupport和實現BeanDefinitionParser類。

兩個類都位於com.alibaba.dubbo.config.spring.schema包下,以下是DubboNamespaceHandler部分代碼:

public class DubboNamespaceHandler extends NamespaceHandlerSupport {
    static {
        Version.checkDuplicate(DubboNamespaceHandler.class);
    }

    public void init() {
        registerBeanDefinitionParser("application",
                new DubboBeanDefinitionParser(ApplicationConfig.class, true));
        registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(
                ModuleConfig.class, true));
        registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(
                RegistryConfig.class, true));
        registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(
                MonitorConfig.class, true));
        registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(
                ProviderConfig.class, true));
        registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(
                ConsumerConfig.class, true));
        registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(
                ProtocolConfig.class, true));
        registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(
                ServiceBean.class, true));
        registerBeanDefinitionParser("reference",
                new DubboBeanDefinitionParser(ReferenceBean.class, false));
        registerBeanDefinitionParser("annotation",
                new DubboBeanDefinitionParser(AnnotationBean.class, true));
    }
}

DubboBeanDefinitionParser由於太長了,大家自行查閱源碼。

定製spring.handlers和spring.schemas

編碼完畢之後,還需要做一些配置工作。我們必須告訴Spring我們準備使用自定義的標簽元素,告訴Spring如何解析元素,否則Spring沒那麼聰明。這裏需要2個配置文件,spring.handlers和spring.schemas(位於META-INF下即可),用於告訴Spring自定義標簽的文檔結構以及解析它的類。兩個文件內容分別如下:

spring.handlers:

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

spring.schemas:

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

注意 \是轉義,一定要加,不然會提示報錯。

spring-context-dubbo.xml

好了,最終呈現給大家的就是這個樣子:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
    xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
    xmlns:dubbo="https://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="https://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        https://code.alibabatech.com/schema/dubbo
        https://code.alibabatech.com/schema/dubbo/dubbo.xsd
        ">
    <!-- 提供方應用信息,用於計算依賴關係  部分代碼-->
    <dubbo:application name="itstyle" />
</beans>

小站:https://blog.52itstyle.com

最後更新:2017-07-11 09:32:23

  上一篇:go  馬雲:創業至今從不應酬,下輩子想做女人
  下一篇:go  分布式服務Dubbo從入門到"精通"之序言