美文网首页
Dubbo学习笔记(二) SPI

Dubbo学习笔记(二) SPI

作者: 云师兄 | 来源:发表于2019-11-03 23:55 被阅读0次

    1. Java SPI

    1.1 概念

    SPI全称是Service Provider Interface,是JDK内置的一种服务提供发现功能,一种动态替换发现的机制。

    1.2 规范

    使用SPI需要遵循下面的规范:

    • 设置META-INF目录,并在下面新建一个services目录

    • 在上面创建的目录下,放置配置文件

    • 使用ServiceLoad.load()方法进行加载

    1.3 示例

    首先新建一个maven项目,结构如下: 1572792821854.png

    下面分步骤进行描述。
    首先新建一个HelloService接口:

    public interface HelloInterface {
        public void sayHello();
    }
    

    以及该接口的两个实例:

    public class ImageHello implements HelloInterface {
        public void sayHello() {
            System.out.println("Image hello!");
        }
    }
    
    public class TextHello implements HelloInterface {
        public void sayHello() {
            System.out.println("Text hello");
        }
    }
    

    然后在resources目录下的META-INF.services目录下新建一个配置文件,文件名要求是接口全路径名,内容是要实现的接口实现类:

    com.spiexample.impl.ImageHello
    com.spiexample.impl.TextHello
    

    并且文件是UTF-8编码的。

    最后在SPIMain这个启动类中进行测试:

    public class SPIMain {
        public static void main(String[] args){
            ServiceLoader<HelloInterface> serviceLoader = ServiceLoader.load(HelloInterface.class);
            if (serviceLoader != null){
                for(HelloInterface helloInterface : serviceLoader){
                    helloInterface.sayHello();
                }
            }
        }
    }
    

    最终输出结果为:

    Image hello!
    Text hello
    

    说明已经成功创建出接口的两个实现类的对象并执行方法了。

    2. Dubbo SPI

    Dubbo SPI相比于Java SPI而言,做了一定的优化和改进。JDK标准的SPI会一次性实例化扩展点所有实现,如果有扩展实现则初始化很耗时,如果没有用上也加载,则浪费资源。如第一小节的例子中,HelloInterface接口有很多实现类,ServiceLoader.load方法返回的serviceLoader对象中封装了所有实现类的实例。所以ServiceLoader实现了Iterable接口,以遍历出所有的实现类。

    Dubbo SPI则不然,它只加载配置文件中的类,并分成不同的种类缓存在内存中,而不会全部初始化,在性能上有更好的表现。

    下面是一个例子,在第一小节的例子上通过Dubbo SPI进行改进。

    首先修改接口类:

    @SPI("impl")
    public interface HelloInterface {
        public void sayHello();
    }
    

    添加了一个注解,并且设置属性为impl,表示接口默认实现为impl。

    然后再定义一个这个接口的实现类:

    public class NewHello implements HelloInterface {
        public void sayHello() {
            System.out.println("new hello!");
        }
    }
    

    然后在META-INF目录下新建一个dubbo目录,再新建一个文件,文件名也是要求是接口HelloInterface的全路径名,内容是:

    impl=com.spiexample.impl.NewHello
    

    impl即对应了接口的一个实现类。

    写完这些后,最后main方法中调用如下:

    HelloInterface helloInterface = ExtensionLoader.
      getExtensionLoader(HelloInterface.class).
      getDefaultExtension();
    helloInterface.sayHello();
    

    最终就成功打印new hello,说明调用实例的就是指定的NewHello。

    相关文章

      网友评论

          本文标题:Dubbo学习笔记(二) SPI

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