java-SPI

java-SPI

起男 667 2021-01-26

java-SPI

什么是spi?

spi全称service provider interface,是java提供的一套用来被第三方实现和扩展的接口,是一种将服务接口与服务分离以达到解耦、大大提升了程序可扩展性的机制。引入服务提供者就是引入了spi接口的实现者,通过本地的注册发现获取到具体的实现类,轻松可插拔

使用

当访问的提供者提供了一种接口的实现之后,需要在classpath下的META-INF/services/目录里创建一个以服务接口命名的文件,这个文件里的内容就是这个接口的具体的实现类。当其它的程序需要这个服务的时候,就可以通过查找这个jar包(一般都是以jar包做依赖)的META-INF/services/中的配置文件,配置文件中有接口的具体实现类名,可以根据这个类名进行加载实例化,就可以使用该服务了。jdk中查找服务的工具类是:java.util.ServiceLoader

应用场景

spi扩展机制应用场景有很多,比如Common-Logging、JDBC、Dubbo、Sharding-JDBC等

jdbc4.0以前,开发人员还需要基于Class.forName("xxx")的方式来装载驱动,jdbc4也基于spi的机制类发现驱动提供商了,可以通过META-INF/services/java.sql.Driver文件里指定实现类的方式来暴露驱动提供者

机制的约定

  1. 在META-INF/services/目录中创建以接口权限定命名的文件,该文件内容为api具体实现类的全限定名
  2. 使用ServiceLoader类动态加载META-INF中的实现类
  3. 如spi的实现类为jar则需要放在主程序ClassPath中
  4. api具体实现类必须有一个不带参数的构造方法

例子

  1. 创建接口

    public interface SpiService {
        void getInfo();
    }
    
  2. 创建实现类

    public class SpiServiceImpl1 implements SpiService {
        @Override
        public void getInfo() {
            System.out.println("info...1");
        }
    }
    
    public class SpiServiceImpl2 implements SpiService {
        @Override
        public void getInfo() {
            System.out.println("info...2");
        }
    }
    
  3. 在resources下创建META-INF/services/com.dqn.spi.service.SpiService文件

    com.dqn.spi.service.impl.SpiServiceImpl1
    com.dqn.spi.service.impl.SpiServiceImpl1
    
  4. 测试

    ServiceLoader<SpiService> load = ServiceLoader.load(SpiService.class);
            for (SpiService spiService : load){
                spiService.getInfo();
            }
    

原文:https://mp.weixin.qq.com/s/hupYoJqVLdUU2Wf3HN1SVw