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

      Dubbo提供了很好的配置xml的方法進行使用,例子以下:html

<?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:rpc="http://code.jiupai.com/schema/rpc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                        http://code.jiupai.com/schema/rpc http://code.jiupai.com/schema/rpc/rpc.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

        <dubbo:application name="dubbo-client"/>
        <dubbo:registry address="zookeeper://127.0.0.1:2181"/>       
        <!--dubbo service-->
        <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl" /> 
        <dubbo:service protocol="dubbo" interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>
        <dubbo:service id="helloService" interface="com.alibaba.dubbo.demo.provider.DemoService"/>
</beans>

這種方式用起來很是方便簡潔,如今大多數開源框架都會提供這種基於xml配置的方式。這些都是基於 Spring 可擴展 Schema 提供自定義配置支持。spring

        雖然基於Spring的標準的Bean配置能夠知足咱們對於系統的簡單配置,可是若是遇到須要配置較爲複雜的或者須要更多的豐富控制的時候,基於標準的Spring的Bean的配置就顯得有點捉襟見肘了。此時有些方法可使用:app

(1)本身使用相關的xml工具類去解析xml定義,而後轉化成目標的配置對象,這種方式能夠實現深度的定製化,可是實現起來比較繁瑣,特別是在配置項很是複雜的時候,解析起來也是一場的繁瑣。框架

(2)使用Spring提供的可擴展Schema的支持,可讓咱們不用重複的去造輪子,從必定程度上減小工做量,而且能夠達到不錯的效果。ide

基於Spring的擴展Schema的方式完成一個自定義配置通常須要如下步驟:工具

a、設計配置屬性和JavaBean 
b、編寫XSD文件 
c、編寫NamespaceHandler和BeanDefinitionParser完成解析工做 
d、編寫spring.handlers和spring.schemas串聯起全部部件 
e、在Bean文件中應用 
下面分析Dubbo是如何基於Spring的可擴展Schema的方式實現簡單配置便可實現服務注入的。this

一、首先咱們拿到Dubbo的配置,查看其在配置文件中的使用:spa

點開標籤: 設計

<dubbo:registry address="zookeeper://127.0.0.1:2181"/>

能夠看到標籤訂義文件(xsd通常存放在classpath下,通常都放在META-INF目錄下):com/alibaba/dubbo/2.4.9/dubbo-2.4.9.jar!/META-INF/dubbo.xsd中的定義以下:code

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

二、xsd還無法讓應用感知到,spring提供了spring.handlers和spring.schemas這兩個配置文件來完成這項工做,這兩個文件須要咱們本身編寫並放入META-INF文件夾中,這兩個文件的地址必須是META-INF/spring.handlers和META-INF/spring.schemas,spring會默認去載入它們,本例中spring.handlers以下所示:

經過com/alibaba/dubbo/2.4.9/dubbo-2.4.9.jar!/META-INF/spring.schemas和com/alibaba/dubbo/2.4.9/dubbo-2.4.9.jar!/META-INF/spring.handlers文件將功能串起來

定義以下:

http\://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd
http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

兩個定義能夠將前面說的dubbo.xsd與對應的解析類com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler關聯起來。

三、com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler解析配置。

NamespaceHandler會根據schema和節點名找到某個BeanDefinitionParser,而後由BeanDefinitionParser完成具體的解析工做。所以須要分別完成NamespaceHandler和BeanDefinitionParser的實現類,Spring提供了默認實現類NamespaceHandlerSupport和AbstractSingleBeanDefinitionParser,簡單的方式就是去繼承這兩個類。Dubbo就是採起這種方式,代碼以下:

//
package com.alibaba.dubbo.config.spring.schema;

import com.alibaba.dubbo.common.Version;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ConsumerConfig;
import com.alibaba.dubbo.config.ModuleConfig;
import com.alibaba.dubbo.config.MonitorConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.ProviderConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.AnnotationBean;
import com.alibaba.dubbo.config.spring.ReferenceBean;
import com.alibaba.dubbo.config.spring.ServiceBean;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

public class DubboNamespaceHandler extends NamespaceHandlerSupport {
    public DubboNamespaceHandler() {
    }

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

    static {
        Version.checkDuplicate(DubboNamespaceHandler.class);
    }
}

能夠看到這個裏面定義了不少的解析器,並且解析是按照順序進行的,具體能夠點進去跟蹤代碼閱讀。

參考:基於Spring可擴展Schema提供自定義配置支持(spring配置文件中 配置標籤支持),裏面介紹的已經很全了 關於Spring的Schema的資料

http://www.cnblogs.com/jifeng/archive/2011/09/14/2176599.html

相關文章
相關標籤/搜索