SPI机制

  SPI 全称Service Provider Interface,一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。可以在运行时,动态为接口替换实现类。可以很容易的通过 SPI 机制为程序提供拓展功能。

  Java SPI 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制。

  Java SPI

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

  定义一个Robot的接口与两个实现类

public interface Robot {
    void sayHello();
}

public class Bumblebee implements Robot {
    @Override
    public void sayHello() {
        System.out.println("Hello, I am Bumblebee.");
    }
}

public class OptimusPrime implements Robot {
    @Override
    public void sayHello() {
        System.out.println("Hello, I am Optimus Prime.");
    }
}

  META-INF/services 文件夹下创建一个文件,名称为 Robot 的全限定名 org.apache.spi.Robot。文件内容为实现类的全限定的类名,如下:

com.smart.spi.Bumblebee
com.smart.spi.OptimusPrime

  测试类

public class SpiTest {

    @Test
    public void sayHello() throws Exception {
        ServiceLoader<Robot> serviceLoader = ServiceLoader.load(Robot.class);
        System.out.println("Java SPI");
        serviceLoader.forEach(Robot::sayHello);
    }
}

     应用场景

  • 数据库驱动加载接口实现类的加载    JDBC加载不同类型数据库的驱动

  • 日志门面接口实现类加载    SLF4J加载不同提供应商的日志实现类

  • Spring     Servlet容器启动初始化org.springframework.web.SpringServletContainerInitializer

  • Spring Boot    自动装配过程中,加载META-INF/spring.factories文件,解析properties文件

  • Dubbo   Dubbo大量使用SPI技术,里面有很多个组件,每个组件在框架中都是以接口的形成抽象出来,例如Protocol 协议接口

       Java SPI源码分析

  

    

posted on 2020-10-30 22:44  溪水静幽  阅读(461)  评论(0)    收藏  举报