dubbo(一)扩展机制SPI

作为一个Microkernel + Plugin 模式的框架, Dubbo 的所有功能点都可被用户自定义扩展所替换,那这是如何实现的呢?

SPI

SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在约定的文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。

1、JDK SPI示例

1、配置文件放在META-INF/services下

//jdk写死的
private static final String PREFIX = "META-INF/services/";                

2、读取配置加载对应的类

/**
 * SPI服务接口
 */
public interface Command {
    public void execute();
}
public class ShutdownCommand implements Command {
    public void execute() {
        System.out.println("shutdown....");  
    }
}
public class StartCommand implements Command {
    public void execute() {
        System.out.println("start....");
    }
}
public class SPIMain {
    public static void main(String[] args) {
        ServiceLoader<Command> loader = ServiceLoader.load(Command.class);
        for (Cmand Cmand : loader) {
            Cmand.execute();
        }
    }
}

运行结果

shutdown....
start....

JDK SPI 缺点
虽然ServiceLoader也算是延迟加载,但是加载是会把配置的类全部实例化,获取也只能通过遍历获取。

Dubbo SPI

Dubbo对JDK的SPI进行了扩展,类名是ExtensionLoader,配置文件采用KV(键值对)的形式,K为名称,V为实现类全限定名。

Dubbo SPI 所需的配置文件需放置在 META-INF/dubbo 路径下,配置内容如下。

optimusPrime = org.apache.spi.OptimusPrime
bumblebee = org.apache.spi.Bumblebee

下面是 Dubbo SPI 的用法(Demo来自官方文档):

public class DubboSPITest {

    @Test
    public void sayHello() throws Exception {
        ExtensionLoader<Robot> extensionLoader = 
            ExtensionLoader.getExtensionLoader(Robot.class);
        Robot optimusPrime = extensionLoader.getExtension("optimusPrime");
        optimusPrime.sayHello();
        Robot bumblebee = extensionLoader.getExtension("bumblebee");
        bumblebee.sayHello();
    }
}

输出如下:

自适应拓展

有些拓展并不想在框架启动阶段被加载,而是希望在拓展方法被调用时,根据运行时参数进行加载,Dubbo使用代理生成对应的类。Dubbo称之为自适应拓展。

应用

Dubbo作为一个开放式平台,所有拓展都可以通过 SPI 机制进行加载的,比如协议、路由、负载均衡、拦截器、注册中心等。

Reference
1、http://dubbo.apache.org/zh-cn/docs/source_code_guide/dubbo-spi.html

猜你喜欢

转载自www.cnblogs.com/walterlee/p/12938716.html