基于 Spring & SPI 实现动态服务配置实践
定义一个接口,如何优雅的根据一个接口来获取该接口的实现类呢?
以 Site 国际化为例,一般是各个国家有各个国家的 Service,各个国际的 Service 由各个国家的 team 维护,那在统一框架下,如何实现获取动态服务,由此 SPI 引入眼帘。
SPI - Service Provider Interface
SPI 全称为(Service Provider Interface),是 JDK 内置的一种服务提供发现机制,它是一种动态替换发现服务实现者的机制。简单地理解,这是建立在面向接口编程下的一种为了使组件可扩展或动态变更实现的规范。
常见的类 SPI 的设计有 JDBC、JNDI、JAXP 等,很多开源框架的内部实现也采用了 SPI。
1、在 mysql-connector-java-xxx.jar 中发现了 META-INF\services\java.sql.Driver 文件
2、在 jcl-over-slf4j-xxxx.jar 中发现了 META-INF\services\org.apache.commons.logging.LogFactory 文件
3、Dubbo 基于 SPI 实现了强大灵活的扩展机制
自定义 SPI
为什么要自定义 SPI ?
在实际应用中,无论是 Java SPI 或是 Spring SPI,都无法服务与工程已有 Spring 容器进行整合。
举个栗子:订单 OrderService 的 Implement 是通过 SPI 方式创建的,可如果 OrderService 实现类中调用了 Spring 容器管理的商品 WareService,则会出现 null 异常,因为 OrderService 实现类的生命周期并没有交给 Spring 容器管理。
基于此,我们可以自己实现一套逻辑,主要包括两点:
1、加载 META-INF 目录下的 spi 接口文件
2、将实例化的 Bean 注册到 Spring 的容器中
具体的实现,访问 Github:https://github.com/linkedkeeper/spi-imp
Reference
https://www.cnkirito.moe/spi/
https://www.jianshu.com/p/7daa38fc9711