我是靠谱客的博主 帅气玫瑰,最近开发中收集的这篇文章主要介绍JDK SPI与Dubbo SPI的实现,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

JDK SPI

SPI全称Service Provider Interface,是提供厂商做插件开发的,如数据库驱动。

Java SPI使用了策略模式,一个接口多种实现。同时具体实现不在程序中指定,而是在程序之外的配置文件配置。

具体实现过程:

1. 新建一个名称为driver的maven工程,定义一个DatabaseDriver接口及对应的方法,打成jar包,供后续实现依赖

public interface DatabaseDriver {
    String buildConection(String msg);
}

2. 新建一个名称为mysql-driver的maven工程,在pom中引入driver工程的依赖,然后创建DatabaseDriver的实现类

public class MysqlDriver implements DatabaseDriver {
    @Override
    public String buildConection(String msg) {
        return "MySQL Driver:" + msg;
    }
}

3. 在mysql-driver工程main文件夹下创建资源文件夹resources,然后再创建目录META-INF/services,在该目录下创建以要实现接口全路径命名的文件:如com.xxx.spi.DatabaseDriver,文件内容为接口的实现的全路径名:com.xxx.spi.MysqlDriver

4. 新建一个名称为java-spi-test的工程,在pom中加入前面两个项目的依赖,可通过以下方式调用具体实现:

public static void main( String[] args ) {
    ServiceLoader<DatabaseDriver> serviceLoader = ServiceLoader.load(DatabaseDriver.class);

    for (DatabaseDriver databaseDriver : serviceLoader) {
        System.out.println(databaseDriver.buildConection("hello"));
    }
}

最后输出:MySQL Driver:hello

由此可以看出main方法中通过java.util.ServiceLoader可以获得接口的所有实现,具体使用哪种实现由用户决定。

 

Dubbo SPI

Dubbo 的扩展点机制是在 JDK SPI 机制上做了改进,引用官网的一段话:

Dubbo 改进了 JDK 标准的 SPI 的以下问题:

  • JDK 标准的 SPI 会一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但如果没用上也加载,会很浪费资源。
  • 如果扩展点加载失败,连扩展点的名称都拿不到了。比如:JDK 标准的 ScriptEngine,通过 getName() 获取脚本类型的名称,但如果 RubyScriptEngine 因为所依赖的 jruby.jar 不存在,导致 RubyScriptEngine 类加载失败,这个失败原因被吃掉了,和 ruby 对应不起来,当用户执行 ruby 脚本时,会报不支持 ruby,而不是真正失败的原因。
  • 增加了对扩展点 IoC 和 AOP 的支持,一个扩展点可以直接 setter 注入其它扩展点。

约定:

在扩展类的 jar 包内,在资源路径META-INF/dubbo(或META-INF/services、META-INF/dubbo/internal)下放置扩展点配置文件,文件名称为接口全限定名且无后缀,文件内容为:配置名=扩展实现类全限定名,多个实现类用换行符分隔。

如果要定义dubbo SPI接口,需要在接口上添加@SPI注解,value为默认实现。

@SPI("dubbo")
public interface Protocol {
    int getDefaultPort();

    @Adaptive
    <T> Exporter<T> export(Invoker<T> var1) throws RpcException;

    @Adaptive
    <T> Invoker<T> refer(Class<T> var1, URL var2) throws RpcException;

    void destroy();
}

以实现org.apache.dubbo.rpc.Protocol接口为例:

1. 首先定义实现类com.xxx.dubbo.spi.impl.MyProtocolImpl

public class MyProtocolImpl implements Protocol {

    @Override
    public int getDefaultPort() {
        return 8888;
    }

    @Override
    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        return null;
    }

    @Override
    public <T> Invoker<T> refer(Class<T> aClass, URL url) throws RpcException {
        return null;
    }

    @Override
    public void destroy() {
    }
}

2. 然后在resources/META-INF/dubbo(或META-INF/services、META-INF/dubbo/internal)目录下创建名称为org.apache.dubbo.rpc.Protocol的配置文件(接口的全限定名)

配置文件内容为:myprotocol=com.xxx.dubbo.spi.impl.MyProtocolImpl(key=value方式)

3. 最后可以通过以下方式调用dubbo的SPI实现类:

public static void main(String[] args) {
    Protocol myprotocol = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension("myprotocol");
    // 输出实现类中的端口号8888
    System.out.println(myprotocol.getDefaultPort());
}

 

最后

以上就是帅气玫瑰为你收集整理的JDK SPI与Dubbo SPI的实现的全部内容,希望文章能够帮你解决JDK SPI与Dubbo SPI的实现所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(34)

评论列表共有 0 条评论

立即
投稿
返回
顶部