什么是SPI机制

SPI全称service provider interface,是jdk内置的一种服务提供发现机制,是java提供的一套用来被第三方实现或者扩展的api,java spi四个主要概念

  • service - 服务:服务是一组接口类,用来定义某些功能或特性,暴露给其它程序调用
  • service provider interface - 服务提供者接口:定义接口,用来被别人去实现
  • service provider - 服务提供者:接口的实现
  • ServiceLoader - 这个类是spi的核心,用赖加载的方式发现和加载服务的实现,它通过classpath的定位服务来实现,并将它们加载到JVM中。

    Demo

    image.png

  • 编写接口与实现类

    1. public interface UserService {
    2. String queryUser();
    3. }
    1. public class CustomerImpl implements UserService {
    2. @Override
    3. public String queryUser() {
    4. System.out.println("=====我是用户实现======");
    5. return null;
    6. }
    7. }
    1. public class MerchantImpl implements UserService {
    2. @Override
    3. public String queryUser() {
    4. System.out.println("=====我是商户实现======");
    5. return null;
    6. }
    7. }
  • 接着在 classpath (及resource)下创建文件夹 META-INF/services,并在文件夹下创建一个文件,名称为:com.plat.paygate.order.spi.UserService(接口的全路径名)

  • 在文件中写上接口的实现类

    1. com.plat.paygate.order.spi.MerchantImpl
    2. com.plat.paygate.order.spi.CustomerImpl
  • 测试 ``` public void test() { ServiceLoader serviceLoader = ServiceLoader.load(UserService.class); Iterator iterator = serviceLoader.iterator(); while (iterator.hasNext()){

    1. UserService userService = iterator.next();
    2. userService.queryUser();

    } }

//输出 =====我是商户实现====== =====我是用户实现====== ```

总结

优点

java是面向接口编程,这样可以让接口与实现类解耦,使得接口与具体业务分离,接口只需要定义标准即可,具体实现由其接入的框架去实现,如java.sql.Driver,定义了响应接口,mysql和oracle可以根据自己的需求各自实现自己的实现类

缺点

  • 不能按需加载。虽然 ServiceLoader 做了延迟载入,但是基本只能通过遍历全部获取,也就是接口的实现类得全部载入并实例化一遍。如果你并不想用某些实现类,或者某些类实例化很耗时,它也被载入并实例化了,这就造成了浪费。
  • 获取某个实现类的方式不够灵活,只能通过 Iterator 形式获取,不能根据某个参数来获取对应的实现类。
  • 多个并发多线程使用 ServiceLoader 类的实例是不安全的。
  • 加载不到实现类时抛出并不是真正原因的异常,错误很难定位。