dubbo源码之——基于SPI的自定义扩展实现

Posted 易君君易

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dubbo源码之——基于SPI的自定义扩展实现相关的知识,希望对你有一定的参考价值。

SPI(串行外设接口)


    即:为某个接口寻找服务实现的机制,就是将装配的控制权移到程序之外,在模块化设计中尤其重要。


    通俗讲便是面向接口编程。


JAVA-SPI

 

       约定如下 :当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。 

 

       代码如下:

 

        1、定义接口

    

 

     2、不同的接口实现类

       dubbo源码之——基于SPI的自定义扩展实现        dubbo源码之——基于SPI的自定义扩展实现     

    3、创建META-INF/services,新建接口全限名文件,内容为要加载的实现类

    dubbo源码之——基于SPI的自定义扩展实现


      4、调用测试


dubbo源码之——基于SPI的自定义扩展实现


dubbo源码之——基于SPI的自定义扩展实现


以上乃java-spi调用


DUBBO-EXTENSION


Dubbo基于SPI实现接口插件的可扩展化,即 Dubbo 的所有功能点都可被用户自定义扩展所替换。


通俗讲便是dubbo支持调用——内部服务接口的——第三方实现。


核心概念:


扩展点 Dubbo是一个灵活的框架,并不强制所有用户都一定使用Dubbo提供架构。如注册中心(Registry),Dubbo提供了zkredis,但如果我们更倾向于其他的注册中心的话,我们可以替换掉Dubbo提供的注册中心。针对这种可被替换的技术实现点我们称之为扩展点


Wrapper Dubbo在加载某个接口的扩展类时候,如果某个实现中有一个拷贝类构造函数,那么该接口实现就是该接口的包装类,此时Dubbo会在真正的实现类上层包装上盖Wrapper。即这个时候从ExtensionLoader中返回的实际扩展类是被Wrapper包装的接口实现类。


Adaptive 这个自适应的扩展点比较难理解,所以这里直接以一个例子来讲解:在RegistryProtocol中有一个属性为Cluster,其中ProtocolCluster都是Dubbo提供的扩展点,所以这时候当我们真正在操作中使用cluster的时候究竟使用的哪一个cluster的实现类呢?是FailbackCluster还是FailoverClusterDubbo在加载一个扩展点的时候如果发现其成员变量也是一个扩展点并且有相关的set方法,就会在这时候将该扩展点设置为一个自适应的扩展点,自适应扩展点(Adaptive)会在真正使用的时候从URL中获取相关参数,来调用真正的扩展点实现类。具体的实现会在下面的源码中详细解释。对于Adaptive的理解其实个人推荐的是Dubbo开发者指南,指南中有对于Adaptive的明确介绍。


Activate 官网的叫法是自激活,其实这个更合适的叫法我认为是

 

代码举例与说明


一:以Protocol协议接口为例说明它的使用。


 1、要扩展的接口Protocol,其中@SPI注解是dubbo自定义注解,用以标注扩展点名字。

 

dubbo源码之——基于SPI的自定义扩展实现

 

dubbo源码之——基于SPI的自定义扩展实现


        2、Protocol的实现类,此处只举DubboProtocol,Protocol有多个实现类,但是默认加载的是DubboProtocol,即dubbo协议,面试时候会问dubbo中有哪些协议,实际是考Protocol有哪些实现接口。


dubbo源码之——基于SPI的自定义扩展实现


    3、Protocol的扩展加载配置,注意此处key为dubbo,因为Protocol接口的@SPI注解指定了扩展点名字为dubbo

 

dubbo源码之——基于SPI的自定义扩展实现


二:从源码分析dubbo扩展的实现。                                                      


    调用规范


dubbo源码之——基于SPI的自定义扩展实现

 

1、dubbo中实现扩展的类是ExtensionLoader


dubbo源码之——基于SPI的自定义扩展实现

 

2、我们主要看ExtensionLoader的getExtensionLoader方法,此处会一层一层进行标注。

dubbo源码之——基于SPI的自定义扩展实现


       1)EXTENSION_LOADERS缓存中不存在时,则new一个对应type的ExtensionLoader


dubbo源码之——基于SPI的自定义扩展实现

 

                   2)getAdaptiveExtension,无非是从缓存取,取不到就新构建                                                                      

dubbo源码之——基于SPI的自定义扩展实现


      3)createAdaptiveExtension——>getAdaptiveExtensionClass,通过SPI读入,然后到生成动态代理。


dubbo源码之——基于SPI的自定义扩展实现


                    4)此处主要看SPI调用,getExtensionClasses——>loadExtensionClasses,其中都会检查缓存是否存在


dubbo源码之——基于SPI的自定义扩展实现


                5)其中META-INF下的已配置了要加载的实现类,然后依次loadDirectory——>loadResource——>loadClass方法,至此完成扩展实现的加载。可见Dubbo的SPI与java SPI相比,要稍显复杂。


                6)剩下主要是根据JAVA的反射机制去读出接口中的所有方法,形成该接口的代理


以下是dubbo扩展的全过程图,摘自网络



       

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


以上是关于dubbo源码之——基于SPI的自定义扩展实现的主要内容,如果未能解决你的问题,请参考以下文章

2. Dubbo原理解析-Dubbo内核实现之基于SPI思想Dubbo内核实现(转)

Dubbo底层源码分析之SPI扩展点

dubbo源码阅读之SPI

Dubbo之SPI源码分析

02.dubbo源码解析之Dubbo扩展点加载

Dubbo的SPI自适应扩展