SPI

13 阅读2分钟

SPI 主要作用是控制权的转化,SPI提供了外部团队(服务)接入的机制,是专门提供给服务提供者或者扩展框架功能的开发者去使用的一个接口。

定义一个标准的接口,第三方库可以实现这个接口,程序运行的时候会根据配置信息动态加载第三方的实现,从而完成动态的扩展的机制。不需要在代码里显示指定该类,进而实现解耦。

其内部会获取线程上下⽂类加载器,用于加载 classpath 中的具体实现类

实际案例

  • Jdbc驱动
  • 很多开源框架里也会借鉴 SPI 的思想,比如 SpringBoot 自动装配,会自动读取 spring.factories 文件进行自动装配

使用规范要素

  1. 规范的配置文件
    1. 必须在 jar 包中 MATE-INF/services 目录
    2. 文件名称:service 接口的全限定名
    3. 文件内容:实现类的全限定名,多个类一个类占一行
  1. 实现类必须具备无参构造方法

源码级深度理解 Java SPI

通过 SPI 机制能够大大地提高接口设计的灵活性,但是 SPI 机制也存在一些缺点,比如:

1.不能按需加载,需要遍历所有的实现,并实例化,然后在循环中才能找到我们需要的实现。如果不想用某些实现类,或者某些类实例化很耗时,它也被载入并实例化了,这就造成了浪费。

2.获取某个实现类的方式不够灵活,只能通过 Iterator 形式获取,不能根据某个参数来获取对应的实现类。(Spring 的BeanFactory,ApplicationContext 就要高级一些了。)

3.多个并发多线程使用 ServiceLoader 类的实例是不安全的