dubbo学习(二)SPI

概述

SPI (Service Provider Interface)是JDK里面的扩展点发现机制。这个机制存在的动机是什么呢?服务发现。 往往我们的系统某个模块底层都有不同的实现,例如数据库的底层实现有 MySQL ,NoSQL 等,而 SPI 根据配置加载具体的实现。

SPI 在dubbo 中

1297993-20200303111643273-75915379.png

具体实现

package com.alibaba.xxx;
 
import org.apache.dubbo.rpc.Protocol;
 
public class XxxProtocol implements Protocol { 
    // ...
}

当我们外界要使用的使用就可以使用如下配置 。

<dubbo:protocol name="xxx" />

扩展点特性

扩展点使用包装类

扩展点使用包装类对真正的实现类进行包装,例如下面 :

public class XxxProtocolWrapper implements Protocol {
    Protocol impl;
 
    public XxxProtocolWrapper(Protocol protocol) { impl = protocol; }
 
    // 接口方法做一个操作后,再调用extension的方法
    public void refer() {
        //... 一些操作
        impl.refer();
        // ... 一些操作
    }
 
    // ...
}

扩展点自动装配

那么知道了某个扩展点需要生成一个类,那么如何生成呢?dubbo 使用了类似于spring 一样的 AOP 生成,对生成过程中的依赖都会生成,然后自动装配。

扩展点选择真正实现

由于我们使用了包装类,那么真正的实现如何引进呢?在哪里引入呢?答:通过 url 来确定真正的实现类。 例如 :

接口类如下:

public interface CarMaker {
    Car makeCar(URL url);
}
 
public interface WheelMaker {
    Wheel makeWheel(URL url);
}

CarMaker 的一个实现类:

public class RaceCarMaker implements CarMaker {
    WheelMaker wheelMaker;
 
    public setWheelMaker(WheelMaker wheelMaker) {
        this.wheelMaker = wheelMaker;
    }
 
    public Car makeCar(URL url) {
        // ...
        Wheel wheel = wheelMaker.makeWheel(url);
        // ...
        return new RaceCar(wheel, ...);
    }
}

当上面执行

// ...
Wheel wheel = wheelMaker.makeWheel(url);
// ...

时,注入的 Adaptive 实例可以提取约定 Key 来决定使用哪个 WheelMaker 实现来调用对应实现的真正的 makeWheel 方法。如提取 wheel.type, key 即 url.get("wheel.type") 来决定 WheelMake 实现。Adaptive 实例的逻辑是固定,指定提取的 URL 的 Key,即可以代理真正的实现类上,可以动态生成。

在 Dubbo 的 ExtensionLoader 的扩展点类对应的 Adaptive 实现是在加载扩展点里动态生成。指定提取的 URL 的 Key 通过 @Adaptive 注解在接口方法上提供。

总结一下几个要点 :

  • 具体实现的配置信息从 URL 中得到。
  • 具体实现类的激活(生成 bean)依靠注解。
  • 扩展类使用wrap 包装类进行封装

参考资料

  • http://dubbo.apache.org/zh-cn/docs/dev/SPI.html

猜你喜欢

转载自www.cnblogs.com/Benjious/p/12402928.html