美文网首页Dubbo
八、Dubbo框架源码分析:dubbo扩展机制实现

八、Dubbo框架源码分析:dubbo扩展机制实现

作者: 还算年轻 | 来源:发表于2020-10-27 09:47 被阅读0次

    一、SPI机制:

    SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。SPI 机制在第三方框架中也有所应用,比如 Dubbo 就是通过 SPI 机制加载所有的组件。不过,Dubbo 并未使用 Java 原生的 SPI 机制,而是对其进行了增强,使其能够更好的满足需求。在 Dubbo 中,SPI 是一个非常重要的模块。基于 SPI,我们可以很容易的对 Dubbo 进行拓展。如果大家想要学习 Dubbo 的源码,SPI 机制务必弄懂。

    package com.example;

    public interface Spi {

        boolean isSupport(String name);

        String sayHello();

    }

    ServiceLoader 会遍历所有 jar 查找 META-INF/services/com.example.Spi 文件

    A 厂商提供实现

    package com.a.example;

    public class SpiAImpl implements Spi {

        public boolean isSupport(String name) {

        return "SPIA".equalsIgnoreCase(name.trim());

    }

    public String syaHello() {

        return “hello 我是厂商 A”;

    }

    A 厂商提供的 jar 包中的 META-INF/services/com.example.Spi 文件内容为:

    com.a.example.SpiAImpl #厂商 A 的 spi 实现全路径类名

    B 厂商提供实现

    package com.b.example;

    public class SpiBImpl implements Spi {

        public boolean isSupport(String name) {

        return "SPIB".equalsIgnoreCase(name.trim());

    public String syaHello() {

        return “hello 我是厂商 B”;

    }

    B 厂商提供的 jar 包中的 META-INF/services/com.example.Spi 文件内容为:

    com.b.example.SpiBImpl #厂商 B 的 spi 实现全路径类名

    ServiceLoader.load(Spi.class) 读 取 厂 商 A 、 B 提 供 jar 包 中 的 文 件 ,ServiceLoader 实现了 Iterable 接口可通过 while for 循环语句遍历出所有实现。

    一个接口多种实现,就如策略模式一样提供了策略的实现,但是没有提供策略的选择, 使用方可以根据 isSupport 方法根据业务传入厂商名来选择具体的厂商。

    public class SpiFactory {

        //读取配置获取所有实现

        private static ServiceLoader spiLoader = ServiceLoader.load(Spi.class);

        //根据名字选取对应实现

        public static Spi getSpi(String name) {

            for (Spi spi : spiLoader) {

                if (spi.isSupport(name) ) {

                    return spi;

                }

            }

        return null;

    }}

    二、dubbo实现的SPI机制:

    1.标记哪些接口支持SPI 机制:Dubbo 提供一个注解 ,通过该注解标记的接口支持SPI功能。

    2.SPI接口实现类的信息从哪里读取?

    3.SPI接口实现类加载流程:

    1、首选获取SPI接口的ExtensionLoader 类,每个接口会缓存ExtensionLoader 类,ExtensionLoader 类相当于ServiceLoader 

    2.通过ExtensionLoader 类加载接口的实现类

    a) 先读取 SPI 注解的 value 值,有值作为默认扩展实现的 key

    b) 依次读取路径的文件

        META-INF/dubbo/internal/ com.alibaba.dubbo.rpc.Protocol

        META-INF/dubbo/ com.alibaba.dubbo.rpc.Protocol

        META-INF/services/ com.alibaba.dubbo.rpc.Protocol

    逐行读取对应的实现类并通过反射构造实现类。

    4.SPI接口实现类加载好了,n个实现类用那个?

    dubbo 提供SPI 接口的决策类:适配器类。

    为什么要创建设配类,一个接口多种实现, SPI 机制也是如此,这是策略模式,但是我们在代码执行过程中选择哪种具体的策略呢。 Dubbo 采用统一数据模式 com.alibaba.dubbo.common.URL( 它是 dubbo 定义的数据模型不是 jdk 的类),它会穿插于系统的整个执行过程, URL 中定义的协 议 类 型 字 段 protocol , 会 根 据 具 体 业 务 设 置 不 同 的 协 议 。url.getProtocol()值可以是 dubbo 也是可以 webservice, 可以是zookeeper 也可以是 redis。

    dubbo有两种适配类的实现方式:

    1、静态@Adaptive

    2、动态生成适配器代码:

    获取对应的策略适配器类:

    1) 生成 Adaptive 代码 code

    2) 利用 dubbo 的 spi 扩展机制获取 compiler 的设配类

    3) 编译生成的 adaptive 代码

    策略适配器类决策逻辑:更加URL 信息

    SPI实现类依赖其他类怎么办?IOC

    IOC 大 家 所 熟 知 的 ioc 是 spring 的 三 大 基 础 功 能 之 一 , dubbo 的ExtensionLoader 在加载扩展实现的时候内部实现了个简单的 ioc 机制来实现对扩展实现所依赖的参数的注入, dubbo 对扩展实现中公有的 set 方法且入参个数为一个的方法,尝试从对象工厂 ObjectFactory 获取值注入到扩展点实现中去。

    1、Dubbo的容器工厂是怎样的?

    dubbo 的容器工厂也是采用SPI 支持扩展。

    它 跟 Compiler 接 口 一 样 设 配 类 注 解 @Adaptive 是 打 在 类AdaptiveExtensionFactory 上的不是通过 javassist 编译生成的。AdaptiveExtensionFactory 持有所有 ExtensionFactory 对象的集合, dubbo内 部 默 认 实 现 的 对 象 工 厂 是SpiExtensionFactory 和SpringExtensionFactory,他们经过 TreeMap 排好序的查找顺序是优先先从SpiExtensionFactory 获取,如果返回空在从 SpringExtensionFactory 获取。

    工厂适配器类:

    静态适配器类查找容器的SPI实现放入List<ExtensionFactory> factories

    1) SpiExtensionFactory 工厂获取要被注入的对象,就是要获取 dubbo spi扩展的实现,所以传入的参数类型必须是接口类型并且接口上打上了@SPI 注解,返回的是一个设配类对象。

    2) SpringExtensionFactory, Dubbo 利用 spring 的扩展机制跟 spring 做了很好的融合。在发布或者去引用一个服务的时候,会把 spring 的容器添加到 SpringExtensionFactory 工厂集合中去, 当 SpiExtensionFactory没有获取到对象的时候会遍历SpringExtensionFactory 中的 spring 容器来获取要注入的对象

    相关文章

      网友评论

        本文标题:八、Dubbo框架源码分析:dubbo扩展机制实现

        本文链接:https://www.haomeiwen.com/subject/wqfpmktx.html