天天看点

java中spi机制解读

关于spi机制大部分人都很陌生,因为我们在开发过程中很少用到,但是实际上这个机制从我们接触java开始就跟我们如影随形。有些人认为使用java很简单,都是调用第三方依赖包,然后结合自己的业务逻辑就可以了,这个机制就是跟第三方有关。

一、概念

SPI 的全名为 Service Provider Interface,目的hi提供接口,让第三方(服务厂商或扩展框架开发者)提供自定义实现的服务功能。例如,JDBC驱动,可以加载MySQL、Oracle、或者SQL Server等。目前有不少框架用它来做服务的扩张发现。

二、使用规则

通过一张图来看看,用SPI需要遵循哪些规范,因为spi毕竟是JDK的一种标准。

java中spi机制解读

SPI约定:

1、在工程的META-INF/services/目录下,以接口的全限定名作为文件名,文件内容为实现接口的服务类;

2、使用ServiceLoader动态加载META-INF/services下的实现类;

3、接口的实现类需含无参构造函数;(因为类默认包含无参构造函数,如果我们没有重载构造函数所以此处可忽略)

SPI 问题考虑:

1、如果在META-INF/services下有接口实现类,存在多个(例如jar包下面也有相应),系统如何处理?

答:会全部加载,java.util.ServiceLoader在加载资源文件时,已经考虑了这个问题。

2、SPI,和Dubbo等相比,区别在哪里?

答:SPI的目的是提供给各种不同服务相同的访问接口。而Dubbo等微服务是将服务拆分形成功能相对独立的、维护性强的服务。两者出发点并不一致。

三、源码解析

在ServiceLoader中已经默认的加载文件路径

java中spi机制解读

在这里指定文件路径;根据这个路径前缀进行拼接读取相关信息

java中spi机制解读

四、ServiceLoader缺点分析

  • 虽然ServiceLoader也算是使用的延迟加载,但是基本只能通过遍历全部获取,也就是接口的实现类全部加载并实例化一遍。如果你并不想用某些实现类,它也被加载并实例化了,这就造成了浪费。
  • 获取某个实现类的方式不够灵活,只能通过Iterator形式获取,不能根据某个参数来获取对应的实现类

五、demo实例

测试用例:https://github.com/73hulu/corejava

继续阅读