java中SPI(服务提供者的接口)

news2024/12/24 16:39:03

java中SPI(服务提供者的接口)

    • 一:什么是SPI
    • 二:java SPI示例
      • 1.SPI服务提供方
      • 2.SPI服务应用方开发者
    • 三:JavaSPI 机制的核心-ServiceLoader

一:什么是SPI

SPI:“服务提供者的接口”,是一种服务发现机制

用于实现框架或库的扩展点,允许在运行时动态地插入或更换组件实现。

它提供了一个框架(JDK1.6后ServiceLoader)来发现和加载服务实现,使得软件模块能够灵活地选择和使用不同的服务提供商。

在这里插入图片描述

在java中通俗讲就是:

  • 对框架或第三方jar包提供者来说可制定规范,提供给开发者可扩展性
  • 对开发者来说可以根据需要轻松替换框架或第三方jar包中提供了SPI机制的接口的实现

二:java SPI示例

1.SPI服务提供方

SPI服务提供方架构图:
在这里插入图片描述
定义接口规范:

public interface SpiService {
    /**
     * 呼叫方式
     */
    void call();
}

加载具体的服务实现:

package com.lmy.config;

import com.lmy.service.SpiService;

import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;

/**
 * @author : lmy
 * @date : 2024/9/14 上午 11:35
 * 加载具体的服务实现
 */
public class SpiServiceLoader {
    private static volatile SpiServiceLoader LOADER;

    private final SpiService spiService;

    private final List<SpiService> spiServiceList;

    /**
     * 加载服务
     * */
    private SpiServiceLoader() {
        ServiceLoader<SpiService> loader = ServiceLoader.load(SpiService.class);
        List<SpiService> list = new ArrayList<>();
        for (SpiService spiService : loader) {
            list.add(spiService);
        }
        spiServiceList = list;
        if (!list.isEmpty()) {
            // 取第一个
            spiService = list.get(0);
        } else {
            spiService = null;
        }
    }

    /**
     * SpiServiceLoader 单例加载
     * */
    public static SpiServiceLoader getLOADER() {
        if (LOADER == null) {
            synchronized (SpiServiceLoader.class) {
                if (LOADER == null) {
                    LOADER = new SpiServiceLoader();
                }
            }
        }
        return LOADER;
    }


    public void call(){
        if(spiServiceList.isEmpty()){
            System.out.println("SpiService服务未加载!");
        }else {
            SpiService spiService = spiServiceList.get(0);
            spiService.call();
        }
    }

}

默认实现:

package com.lmy.service.impl;

import com.lmy.service.SpiService;

/**
 * @author : lmy
 * @date : 2024/9/14 上午 10:58
 * 默认实现
 */
public class SpiServiceImpl implements SpiService {
    @Override
    public void call() {
        System.out.println("默认手机呼叫");
    }
}

指定服务实现方式:
须在resource下创建META-INF.services,文件名为接口全限定类名,配置为需要被加载的接口实现类的全限定类名
在这里插入图片描述

com.lmy.service.impl.SpiServiceImpl

项目打包发布本地:
在这里插入图片描述

2.SPI服务应用方开发者

开发者引入jar包使用服务:

<dependency>
    <groupId>com.lmy</groupId>
    <artifactId>SPI-interface</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
package com.lmy.Spi;

import com.lmy.config.SpiServiceLoader;
import org.junit.Test;

/**
 * @author : lmy
 * @date : 2024/9/14 上午 11:48
 */
public class SpiTest {

    @Test
    public void spiTest () {
        SpiServiceLoader loader = SpiServiceLoader.getLOADER();
        loader.call();
    }
}

执行结果:
在这里插入图片描述
开发者根据需要扩展替换为自己的服务实现:

package com.lmy.Spi.service;

import com.lmy.service.SpiService;

/**
 * @author : lmy
 * @date : 2024/9/14 下午 2:09
 */
public class SpiServiceNewImpl implements SpiService {
    @Override
    public void call() {
        System.out.println("卫星直呼");
    }
}

在这里插入图片描述

com.lmy.Spi.service.SpiServiceNewImpl

执行结果:
在这里插入图片描述

三:JavaSPI 机制的核心-ServiceLoader

上面代码可见是通过ServiceLoader 去加载具体的服务实现的
在这里插入图片描述
ServiceLoader 是从JDK1.6 开始提供的一个类,用于加载服务提供者。

进入源码可见:
其中 String PREFIX = “META-INF/services/”;
这个就是JDK的SPI功能规定的具体服务实现的配置信息文件所在的目录 META-INF/services/
在这里插入图片描述
JDK的SPI规定 服务实现者需要在 META-INF/services/ 目录下 新建文件名为 SPI接口全限定类名的文件
文件内容为 服务实现者需要被加载的具体类的全限定类名

具体源码底层实现参考:https://blog.csdn.net/qq_37883866/article/details/139000021 中第3点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2136043.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

USART—串口数据包

1.HEX数据包定义 数据包的作用是把一个个单独的数据给打包起来&#xff0c;方便我们进行多字节的数据通信&#xff0c;在实际应用中&#xff0c;我们可能需要把多个字节打包为一个整体进行发送&#xff0c;比如说&#xff0c;我们有个陀螺仪传感器&#xff0c;需要用串口发送数…

git 你要如何打开这个文件

终端输入git命令都会弹出这个框 解决方案&#xff1a; 参考文章&#xff1a;在vscode终端上运行 npm 会询问 “你要如何打开这个文件“_安装 npm脚手架提示你要如何打开-CSDN博客 get-command git后删除对应文件 请注意不要删错了&#xff0c;正常get-command git后对应的是…

微型导轨加工环境需避免的隐患!

微型导轨是一种小巧精密的线性定位解决方案&#xff0c;其高速度、低噪音的特点使得它在现代制造业中扮演着越来越重要的角色。而微型导轨对于加工环境的要求主要体现在以下几个方面&#xff1a; 1、温度控制&#xff1a;加工环境需要保持在适宜的温度范围内&#xff0c;过高或…

【西电电装实习】5. 无人机模块及作用、上位机的操作

文章目录 前言一、硬件结构电源、电源电压测试电路晶振外围陀螺仪信号放大电路及天线空心杯&#xff08;电极&#xff09;驱动电路 软件设置整机装配PID 参数设置公式 参考文献 前言 西电电装实习&#xff0c;无人机原理图、上位机的调节方法 一、硬件结构 电源、电源电压测…

RabbitMQ 基础入门

文章内容是学习过程中的知识总结&#xff0c;如有纰漏&#xff0c;欢迎指正 文章目录 前言 1. 重要概念 1.1 Publisher 1.2 Message 1.3 Exchange 1.4 BindingKey 1.5 Routingkey 1.6 Queue 1.7 Consumer 1.8 Connection 1.9 Channel 1.10 Virtual Host 1.11Broker 2. RabbitMQ…

个人学习笔记7-5:动手学深度学习pytorch版-李沐

#人工智能# #深度学习# #语义分割# #计算机视觉# #神经网络# 计算机视觉 13.10 转置卷积 例如&#xff0c;卷积层和汇聚层&#xff0c;通常会减少下采样输入图像的空间维度&#xff08;高和宽&#xff09;。然而如果输入和输出图像的空间维度相同&#xff0c;在以像素级分类…

手机玩机常识____展讯芯片刷机平台ResearchDownload的一些基本常识与问题解决

展讯ResearchDownload工具 展讯芯片的刷机工具--ResearchDownload下载工具"是一款专为用户设计的高效、便捷的下载管理软件&#xff0c;它能够帮助用户快速、稳定地从互联网上获取各种文件。这款工具以其强大的功能和良好的用户体验&#xff0c;在众多展讯芯片下载工具中脱…

计算机网络30——Linux-gdb调试命令makefile

1、开始调试 编译时带-g为调试&#xff0c;带调试信息编译后的可执行文件更大 2、进入调试 使用gdb 可执行文件名——进入调试 失败版&#xff1a; 成功版&#xff1a; 3、l命令 l什么都不加——列出10行代码 l 行号——行号的行在中间&#xff0c;向上向下展示10行 4、st…

ppt文件怎么压缩变小一些?8种压缩PPT文件的方法推荐

ppt文件怎么压缩变小一些&#xff1f;在现代工作环境中&#xff0c;PPT文件常常是我们展示信息和分享想法的主要工具。然而&#xff0c;当这些文件变得庞大时&#xff0c;它们不仅会占用大量的存储空间&#xff0c;还可能导致处理速度变慢&#xff0c;影响整体工作效率。这种情…

GIS在线监测SF6密度微水定量检漏仪传感器专用波纹管免焊接格兰头

SF6密度微水在线监测装置配套M12母头5孔格兰头穿波纹管连接器&#xff0c;该传感器能够监测SF6气体的露点&#xff0c;从而实现对SF6气体在线监测。 原理 SF6露点在线监测传感器是一种可以监测SF6气体露点的传感器它的工作原理是通过吸收SF6气体中的水分子来测量SF6气体的露点。…

Jetpack PDF库:解锁Android应用中的PDF功能

Jetpack PDF库&#xff1a;解锁Android应用中的PDF功能 在 Android 开发中&#xff0c;加载 PDF 文件是一个比较常见的需求&#xff0c;但就是这么一个比较常见的功能&#xff0c;原生并没有提供一个比较好的方案&#xff0c;而隔壁 IOS 中实现却是很方便的。。。 下面是当前…

Stream流的思想和获取Stream流

首先介绍流的概念&#xff1a; 流可以理解为一条流水线&#xff0c;在这条流水线中有许多操作&#xff0c;比如筛选所需要的数据&#xff0c;输出打印等&#xff0c; 经过这条流水线&#xff0c;可以获取到自己所需要的数据&#xff1a; -->所以&#xff1a; Stream流的作…

GEE 按范围导出 Sentinel-2 卫星影像

Sentinel-2 卫星提供了高分辨率的地表覆盖图像&#xff0c;广泛应用于农业监测、城市规划、环境变化分析等诸多领域。在 Google Earth Engine (GEE) 中&#xff0c;我们能够按特定地理范围导出这些影像&#xff0c;以支持更深入的研究和分析。 使用方法 &#x1f4bb; GEE 提供…

汽车租赁系统1.0版本

汽车租赁系统1.0版本比较简陋&#xff0c;以后还会有2.0、3.0……就像《我爱发明》里面的一代机器二代机器&#xff0c;三代机器一样&#xff0c;是一个迭代更新的过程&#xff08;最近比较忙&#xff0c;可能会很久&#xff09;&#xff0c;这个1.0版本很简陋&#xff0c;也请…

Visual Studio Code 高效开发 C/C++ 插件推荐

Visual Studio Code 高效开发插件 C/C 由 Microsoft 提供的官方插件&#xff0c;支持语法高亮、智能感知、调试等功能&#xff0c;是 C/C 开发的基础插件。 C/C Themes 由 Microsoft 提供的官方主题插件&#xff0c;它旨在增强 C 和 C 代码的编辑体验&#xff0c;通过提供代码…

性能诊断的方法(五):架构和业务诊断

关于性能诊断的方法&#xff0c;我们可以按照“问题现象—直接原因—问题根源”这样一个思路去归纳。我们先从问题的现象去入手&#xff0c;包括时间的分析、资源的分析和异常信息的分析。接下来再去分析产生问题现象的直接原因是什么&#xff0c;这里我们归纳了自上而下的资源…

江协科技STM32学习- P13 TIM定时器中断

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

ESP32开发 -- VSCODE+PlatformIO环境安装

参看官网安装&#xff1a;PlatformIO IDE for VSCode 一、安装PlatformIO IDE 参看&#xff1a;日常生活小技巧 – Visual Studio Code 简单使用 扩展中搜索platformIO IDE 当安装完提示重启之后。 打开一个要创建新工程的文件夹&#xff1a; 点击 Create New Project&…

10大差异!Linux运维VS云计算运维深度解析

在当今这个信息技术飞速发展的时代&#xff0c;云计算与容器化技术已经变得无处不在。 随着这些技术的广泛应用&#xff0c;企业对于如何高效、稳定地运维自己的系统和服务提出了更高的要求。 Linux运维和云计算运维作为两种不同的运维模式&#xff0c;它们各自在技术实现、管…

AI问答-HTTP:理解 Content-Disposition

一、简介 Content-Disposition是HTTP协议中的一个响应头字段&#xff0c;它主要用于指示如何处理响应的内容以及如何呈现给用户。这个字段是MIME协议类型的扩展&#xff0c;用于指导MIME用户代理&#xff08;如浏览器&#xff09;如何显示附加的文件。Content-Disposition的主…