• SPI 服务提供者接口


    ServiceLoader

    SPI 全名 Service Provider Interface ,是java提供的 一个 服务接口拓展机制。使用SPI 可以轻松的修改接口的实现方式。

    例子代码:

    创建一个接口:

    /**
     * 描述
     *
     * @Author ZHANGYUKUN
     * @Date 2022/6/27
     */
    public interface MyInterface {
    
    
        String doSome();
    
    }
    

      创建2个实现类:

    /**
     * 描述
     *
     * @Author ZHANGYUKUN
     * @Date 2022/6/27
     */
    public class Impl1 implements MyInterface {
        @Override
        public String doSome() {
            return "Impl1";
        }
    }
    
    /**
     * 描述
     *
     * @Author ZHANGYUKUN
     * @Date 2022/6/27
     */
    public class Impl2 implements MyInterface {
        @Override
        public String doSome() {
            return "Impl2";
        }
    }
    

      

      

    然后再classpath下面创建 META-INF/services 两个目录

    在 META-INF.services 里面建一个文件名为接口全称的文件:com.lomi.spi.MyInterface

    文件里面写着接口的实现类的全类名:com.lomi.spi.Impl2

    然后我们通过 ServiceLoader 获取接口实现,可以拿到我们指定接口实现类。

    package com.lomi.spi;
    
    import java.util.Iterator;
    import java.util.ServiceLoader;
    
    /**
     * 描述
     *
     * @Author ZHANGYUKUN
     * @Date 2022/6/27
     */
    public class Main {
    
        public static void main(String[] args) {
            ServiceLoader<MyInterface> loadedDrivers = ServiceLoader.load(MyInterface.class);
            Iterator<MyInterface> driversIterator = loadedDrivers.iterator();
            while(driversIterator.hasNext()) {
                MyInterface myInterface =   driversIterator.next();
    
                System.out.println( myInterface.getClass() );
            }
    
            System.out.println( "over.................");
        }
    }
    

      

    很多jar都是通过这种方式来切换接口实现类的,比如 SLF4j 导入对应的装换包,就会换成对应的实现, 原理就是 对应的实现包里面 指定了实现类

    dubbo 的 SPI 也是类似的机制,但是支持  实现key名字=实现类全名格式,,并且可以在接口上指定默认使用那个key对应的实现,获取接口实现类是通过 ExtensionLoader 来获取的

    获取指定 key 的实现类,和查看有那些实现

    public static void main(String[] args) {
    ExtensionLoader<Filter> extensionLoader = ExtensionLoader.getExtensionLoader(Filter.class);

    //获取指定实现
    Filter filter = extensionLoader.getExtension("dubboExceptionFilter");
    System.out.println(filter.getClass());

    //打印有那些实现
    extensionLoader.getSupportedExtensions().forEach((itemKey) -> {
    System.out.println(itemKey);
    });
    }

      

    如果要在接口上指定默认实现可以使用直接 @SPI(“默认实现的key”)

  • 相关阅读:
    转:imageNamed和dataWithContentsOfFile的区别
    [内存管理实践 之 1]在返回按钮中,释放内存
    转:当程序崩溃的时候怎么办 Part2
    iOS 内存管理,我们需要一套切实可行的实践指导书,而不是理论指导书
    转 iOS程序中调用系统自带应用(短信,邮件,浏览器,地图,appstore,拨打电话)
    iOS笔记:内存管理
    转:【图文教程】创建Xcode自定义模板
    判断两个数的大小,返回其中的大者/小者
    iOS全局变量与属性的内存管理
    UIImage 详解
  • 原文地址:https://www.cnblogs.com/cxygg/p/16418037.html
Copyright © 2020-2023  润新知