首页 > 编程语言 >什么是Java中的SPI机制

什么是Java中的SPI机制

时间:2024-02-23 16:48:28浏览次数:28  
标签:Java 接口 SPI MyService 机制 ServiceLoader 加载

SPI,全称 Service Provider Interface,是Java中提供的一种服务发现机制
它允许应用程序动态地加载和使用第三方提供的服务实现,而无需在代码中引用这些实现类。
Java SPI是基于接口编程思想的具体体现,通过将服务接口和其实现分离,从而具备更好的可扩展性和可维护性

如何定义一个Java SPI
1.定义一组接口

public interface MyService {
    void doSomething();
}

2.提供一个或多个实现了该接口的实现类,作为服务提供者

public class MyServiceProvider1 implements MyService {
    public void doSomething() {
        System.out.println("Provider 1 is doing something");
    }
}

public class MyServiceProvider2 implements MyService {
    public void doSomething() {
        System.out.println("Provider 2 is doing something");
    }
}

3.配置文件
在 src/main/resources下新建META-INF/services目录,同时新增一个以接口的全限定名com.example.MyService命名的文件,内容是要应用的实现类的全限定名
注意:每个实现类的全限定名占据一行

com.example.MyServiceProvider1
com.example.MyServiceProvider2

4.使用ServiceLoader来加载该接口下的服务提供者

ServiceLoader<MyService> loader = ServiceLoader.load(MyService.class);
for (MyService service : loader) {
    service.doSomething();
}

//for循环等价于如下代码
Iterator var2 = load.iterator();
while(var2.hasNext()){
  MyService service=(MyService)var2.next();
  service.doSomething();
}
执行结果
1.Provider 1 is doing something
2.Provider 2 is doing something

实现原理
首先看下ServiceLoader类的几个重要的成员变量

结合源码,总结 Java SPI实现的流程如下:
1.调用ServiceLoader.load()方法会先创建一个新的ServiceLoader,并实例化类中的成员变量

2.调用iterator()方法获取一个迭代器对象:
2.1 ServiceLoader会先判断providers对象中是否有缓存实例对象,如果存在则直接返回

2.2 如果不存在,则执行类的加载操作:
2.2.1 读取 META-INF/services/+指定接口的全限定名下的配置文件,获取所有能被实例化的类的全类限定名
2.2.2 通过反射加载并实例化对象并放入providers缓存中
2.2.3 返回该实例对象

SPI的应用场景
1.数据库驱动程序加载
JDBC为了实现可插拔的数据库驱动,在Java.sql.Driver 接口中定义了一组标准的API规范,而具体的数据库厂商则需要实现这个接口,以提供自己的数据库驱动程序。
在Java中,JDBC驱动程序的加载就是通过SPI机制实现的
2.日志框架的实现
流行的开源日志框架,如Log4j、SLF4J和Logback等,都采用了SPI机制。用户可以根据自己的需求选择合适的日志实现,而不需要修改代码
3.Srping框架
Spring框架中的Bean加载机制就使用了SPI思想,通过读取classpath下的META-INF/spring.factories文件来加载各种自定义的Bean
4.Dubbo框架
Dubbo框架也使用了SPI思想,通过接口注解@SPI声明扩展点接口,并在classpath下的META-INF/dubbo目录中提供实现类的配置文件,来实现扩展点的动态加载

标签:Java,接口,SPI,MyService,机制,ServiceLoader,加载
From: https://www.cnblogs.com/zhao-zong-yu-hai/p/18029868

相关文章

  • Java事件侦听器学习记录
    前言我们监听事件之前要有事件源source,创建事件源(Event),发布事件(publishEvent),然后才能到监听事件。事件驱动机制是观察者模式(称发布订阅)具体实现,事件对象(Event)相当于被观察对象(Subject),事件监听(EventListener)相当于观察者(Observer)1、包结构(个人): 2、创建事件源(Event)......
  • Docker启动Aserospike
    Docker安装Aseropike找了一大堆,发现Aserospike的资料太少了(主要是官方文档,好像没有中文的)看了很多的安装部署,一直不满意,于是直接上Docker。这样就简单多了。Docker安装我看很多人都直接在Docker服务,但是最简单的还是直接下载DockerDesktop。mac:https://docs.docker.com/des......
  • java面向对象之封装-抽象-继承-组合-多态五种概念一网打尽
    说明曾经在学习java面向对象时,你是否会为面向对象的封装-继承-抽象-多态-组合等各种概念搞得稀里糊涂,乃至反复阅读,背诵其相关概念,结果一段时间过后又还给了时间。。。这种经历简直令人发指,让人无法忍受,难道就没有哪个地方能把它一次说清楚,老百姓看了以后纷纷醍醐灌顶,不再重蹈覆......
  • TDC7200+STM32模拟SPI驱动测量脉冲时差
    TDC7200数据手册:https://www.ti.com/cn/lit/ds/symlink/tdc7200.pdf?ts=1708671736079&ref_url=https%253A%252F%252Fso.szlcsc.com%252FTDC7200硬件电路: TDC7200驱动程序,TDC7200有两种模式,使用的是模式2模拟SPI:SPI写数据:voidSPI_Write_Byte(uint8_tdata){   uint8_t......
  • java中 break和continue区别
    breakcontinue◆break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环不执行循环中剩余的语句。(break语句也在switch语句中使用)◆continue语句用在循环语句体中,用于终止某次循环过程,即跳过循环体中尚未执行的语句接着进行下一次是否执行循环的判......
  • java的基本循环结构之For循环
    1、For循环虽然所有循环结构都可以用while或者do...while表示,但Java提供了另一种语句--for循环,使一些循环结构变得更加简单。◆for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构。◆for循环执行的次数是在执行前就确定的。语法格式如下:for(初始化;布尔表......
  • python调用Javascript实践
    一、背景知识1、Node.jsjavacript的运行环境有两个:浏览器、node.jsNode.js是一个开源与跨平台的JavaScript运行时环境。它是一个可用于几乎任何项目的流行工具!Node.js在浏览器外运行V8JavaScript引擎(GoogleChrome的内核)。这使Node.js表现得非常出色。运行js的命......
  • java 异步导出zip压缩包
    需求:图片文件太大,采用压缩包下载/** *图片zip压缩包下载 *@paramresponse *@paramzipName压缩包名字 *@paramurls文件图片下载URL路径 *@paramimagesUrlsURL与对应文件名字map *@throwsException */publicstaticvoidexportZip(HttpServletRespon......
  • cinder卷保留机制
     默认情况下,当您删除一个卷时,该卷的状态会变为 deleted,但它仍然会保留在数据库中,直到一个后台任务(通常是 cinder-volume 服务中的 volume_expire)运行并清理这些已标记为删除的卷。这个任务的运行频率可以通过配置文件的设置来控制。具体来说,您可以查看 cinder.conf 配置......
  • java的基本循环结构之while循环
    1、while循环◆while是最基本的循环,它的结构为:while(布尔表达式){//循环内容只要布尔表达式为true,循环就会一直执行下去。我们大多数情况是会让循环停止下来的,我们需要一个让表达式失效的方式来结束循环少部分情况需要循环一直执行,比如服务器的请求响应监听等。循环条件一......