目录
Java SPI
简介
SPI 全称 Service Provider Interface,是 Java 提供的,旨在由第三方实现或扩展的 API,它是一种用于动态加载服务的机制。
Java 中 SPI 机制主要思想是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要,其核心思想就是解耦
设计思想:面向接口+配置文件+反射
个人理解:首先服务端加载所有可能的类,用户在 src/main/resources/ 下建立 /META-INF/services 目录并且建立以接口命名相应的文件,文件内容为要应用的实现类的全限定类名,即可按需调用!
四要素
- SPI 接口:为服务提供者实现类约定的的接口或抽象类。
- SPI 实现类:实际提供服务的实现类。
- SPI 配置:Java SPI 机制约定的配置文件,提供查找服务实现类的逻辑。配置文件必须置于 META-INF/services 目录中,并且,文件名应与服务提供者接口的完全限定名保持一致。文件中的每一行都有一个实现服务类的详细信息,同样是服务提供者类的完全限定名称。
- ServiceLoader:Java SPI 的核心类,用于加载 SPI 实现类。ServiceLoader 中有各种实用方法来获取特定实现、迭代它们或重新加载服务。
优点
- 大大提高接口设计的灵活性
- 基于面向接口编程,优雅地实现模块之间的解耦
缺点
- 不能按需加载,需要遍历所有的实现,并实例化,然后在循环中才能找到我们需要的实现。如果不想用某些实现类,或者某些类实例化很耗时,它也被载入并实例化了,这就造成了浪费
- 获取某个实现类的方式不够灵活,只能通过 Iterator 形式获取,不能根据某个参数来获取对应的实现类
- 多个并发多线程使用 ServiceLoader 类的实例不安全
应用场景
- JDBC
- SLF4J
- Servlet容器初始化
JavaSPI和SpringBoot自动配置对比
JavaSPI设计思想
- 使用约定的配置文件
- 提供Jar包同时提供配置文件
- 高内聚低耦合,兼具代码和配置
- 使用ClassLoader的getResource和getResources方法,来读取classpath中的配置文件
SpringBoot自动配置的核心实现
- 使用约定的配置文件
- 文件路径:META-INF/spring.factories
- 文件内容:key=value1,value2...(key是EnableAutoConfiguration的类名,value是自动配置类的类名)
- 提供自动配置类的Jar包,也同时提供配置文件META-INF/spring.factories