设计模式 - SPI(Service Provider Interface)模式


参考

清幽之地 https://www.jianshu.com/p/3a3edbcd8f24

 

一、什么是SPI

SPI ,全称为 Service Provider Interface,是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。

这一机制为很多框架扩展提供了可能,比如在Dubbo、JDBC中都使用到了SPI机制。我们先通过一个很简单的例子来看下它是怎么用的。



二、jdk的SPI

 

代码

首先,我们需要定义一个接口,SPIService

package com.viewscenes.netsupervisor.spi; public interface SPIService { void execute(); } 

然后,定义两个实现类,没别的意思,只输入一句话。

package com.viewscenes.netsupervisor.spi; public class SpiImpl1 implements SPIService{ public void execute() { System.out.println("SpiImpl1.execute()"); } } ----------------------我是乖巧的分割线---------------------- package com.viewscenes.netsupervisor.spi; public class SpiImpl2 implements SPIService{ public void execute() { System.out.println("SpiImpl2.execute()"); } } 

最后呢,要在ClassPath路径下配置添加一个文件。文件名字是接口的全限定类名,内容是实现类的全限定类名,多个实现类用换行符分隔。
文件路径如下:


 
SPI配置文件位置

内容就是实现类的全限定类名:

com.viewscenes.netsupervisor.spi.SpiImpl1
com.viewscenes.netsupervisor.spi.SpiImpl2

测试

然后我们就可以通过ServiceLoader.load或者Service.providers方法拿到实现类的实例。其中,Service.providers包位于sun.misc.Service,而ServiceLoader.load包位于java.util.ServiceLoader

public class Test { public static void main(String[] args) { Iterator<SPIService> providers = Service.providers(SPIService.class); ServiceLoader<SPIService> load = ServiceLoader.load(SPIService.class); while(providers.hasNext()) { SPIService ser = providers.next(); ser.execute(); } System.out.println("--------------------------------"); Iterator<SPIService> iterator = load.iterator(); while(iterator.hasNext()) { SPIService ser = iterator.next(); ser.execute(); } } } 

两种方式的输出结果是一致的:

SpiImpl1.execute() SpiImpl2.execute() -------------------------------- SpiImpl1.execute() SpiImpl2.execute()


优缺点

优点:将业务代码和具体实现类解耦,方便扩展。如需增加新逻辑,无需修改主流程,直接在PI配置文件增加实现类的全限定名即可。

缺点:颗粒度不够细,无法准确定位某一个实现类。要执行就执行所有的实现类。

 

三、Dubbo 的 SPI(对jdk SPI的颗粒度改进)

Dubbo的配置文件

cluster这里可以准确制定一个实现类

SPI配置文件

和jdk只包含实现类的全限定名不同,这里是key value 模式

 

 

 

 
 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM