zoukankan      html  css  js  c++  java
  • 设计模式

    参考

    清幽之地 https://www.jianshu.com/p/3a3edbcd8f24

    一、什么是SPI

    SPI ,全称为 Service Provider Interface,是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。

    这一机制为很多框架扩展提供了可能,比如在Dubbo、JDBC中都使用到了SPI机制。我们先通过一个很简单的例子来看下它是怎么用的。



    二、jdk的SPI

    代码

    首先,我们需要定义一个接口,SPIService

    package com.viewscenes.netsupervisor.spi;
    public interface SPIService {
        void execute();
    }
    

    然后,定义两个实现类,没别的意思,只输入一句话。

    package com.viewscenes.netsupervisor.spi;
    public class SpiImpl1 implements SPIService{
        public void execute() {
            System.out.println("SpiImpl1.execute()");
        }
    }
    ----------------------我是乖巧的分割线----------------------
    package com.viewscenes.netsupervisor.spi;
    public class SpiImpl2 implements SPIService{
        public void execute() {
            System.out.println("SpiImpl2.execute()");
        }
    }
    

    最后呢,要在ClassPath路径下配置添加一个文件。文件名字是接口的全限定类名,内容是实现类的全限定类名,多个实现类用换行符分隔。
    文件路径如下:


     
    SPI配置文件位置

    内容就是实现类的全限定类名:

    com.viewscenes.netsupervisor.spi.SpiImpl1
    com.viewscenes.netsupervisor.spi.SpiImpl2
    

    测试

    然后我们就可以通过ServiceLoader.load或者Service.providers方法拿到实现类的实例。其中,Service.providers包位于sun.misc.Service,而ServiceLoader.load包位于java.util.ServiceLoader

    public class Test {
        public static void main(String[] args) {    
            Iterator<SPIService> providers = Service.providers(SPIService.class);
            ServiceLoader<SPIService> load = ServiceLoader.load(SPIService.class);
    
            while(providers.hasNext()) {
                SPIService ser = providers.next();
                ser.execute();
            }
            System.out.println("--------------------------------");
            Iterator<SPIService> iterator = load.iterator();
            while(iterator.hasNext()) {
                SPIService ser = iterator.next();
                ser.execute();
            }
        }
    }
    

    两种方式的输出结果是一致的:

    SpiImpl1.execute()
    SpiImpl2.execute()
    --------------------------------
    SpiImpl1.execute()
    SpiImpl2.execute()


    优缺点

    优点:将业务代码和具体实现类解耦,方便扩展。如需增加新逻辑,无需修改主流程,直接在PI配置文件增加实现类的全限定名即可。

    缺点:颗粒度不够细,无法准确定位某一个实现类。要执行就执行所有的实现类。

    三、Dubbo 的 SPI(对jdk SPI的颗粒度改进)

    Dubbo的配置文件

    cluster这里可以准确制定一个实现类

    SPI配置文件

    和jdk只包含实现类的全限定名不同,这里是key value 模式

     
     
  • 相关阅读:
    IKAnalyzer兼容Lucene 5.4.0版本抛出异常?
    Lucene--FuzzyQuery与WildCardQuery(通配符)
    Lucene之模糊、精确、匹配、范围、多条件查询
    CentOS6.5中使用 iperf 检测主机间网络带宽
    文件切割
    CURL命令测试网站打开速度
    不限定访问,支持跨域
    Mysql错误: ERROR 1205: Lock wait timeout exceeded try restarting transaction解决办法
    tomcat链接mysql时超时报错java.io.EOFException: Can not read response from server. Expected to read 4 bytes,
    分享一个很好的工具网址
  • 原文地址:https://www.cnblogs.com/frankcui/p/13407458.html
Copyright © 2011-2022 走看看