SPI(Service Provider Interface)概述
- 定义:SPI是一种动态替换发现机制,用于实现接口与实现的解耦,提高框架的可扩展性。
- 核心思想:解耦和方便扩展。
Java SPI
- 约定规范:
- 扩展类文件放在
META-INF/services/
目录下。 - 文件名是接口的全限定名,内容为实现类的全限定名。
- 扩展类文件放在
- 加载方式:
ServiceLoader<ISearch> serviceLoader = ServiceLoader.load(ISearch.class);
- 优缺点:
- 优点:接口与实现分离。
- 缺点:一次性实例化所有扩展实现,资源浪费;不能按需加载。
Spring SPI
- 约定规范:
- 文件放在
META-INF/
目录下,名为spring.factories
。 - 文件内容为键值对,键为接口全限定名,值为实现类的全限定名,多个实现用逗号分隔。
- 文件放在
- Spring Boot 3.0 后:
- 可在
META-INF/spring/
下的org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件中配置。
- 可在
- 加载方式:
List<PropertySourceLoader> propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class, getClass().getClassLoader());
- 优缺点:
- 优点:不同接口扩展写在一个文件中,方便管理和扩展。
- 缺点:没有实现按需加载,需要自定义加载逻辑。
Dubbo SPI
- 约定规范:
- 接口必须加
@SPI
注解。 - 配置文件可放在四个目录下,文件名为接口的全限定名。
- 内容为键值对,键为短名称,值为实现类的全限定名。
- 接口必须加
- 基础加载方式:
ExtensionLoader<IBusinessService> extensionLoader = ExtensionLoader.getExtensionLoader(IBusinessService.class);
- 自适应扩展:
- 静态方式:使用
@Adaptive
注解的类,如AdaptiveCompiler
。 - 动态方式:运行时动态生成
Adaptive
类,如Protocol$Adaptive.class
。
- 静态方式:使用
- 自动激活:
- 使用
@Activate
注解,根据入参动态选择实现类,如GenericFilter
。
- 使用
总结
- SPI机制是提高软件模块化和可扩展性的关键技术。
- Java SPI、Spring SPI和Dubbo SPI各有特点,适用于不同的场景和需求。
- 了解和掌握SPI机制有助于更好地使用和扩展现有框架。