【学习笔记】java SPI机制

目录

      • 实现:
      • 示例:
      • 注意事项:

Java SPI (Service Provider Interface) 是 Java 提供的一套用来发现和加载第三方服务的机制。SPI 的主要目的是为了解耦框架与插件(服务提供商)之间的依赖关系,使得框架能够灵活地在运行时根据配置加载不同的服务实现。

实现:

  1. 接口定义:定义一个接口或抽象类,声明一些方法作为服务规范。

  2. 服务提供者:实现上述接口或抽象类的具体类,这些实现类通常被打包在独立的 jar 文件中,并且在该 jar 文件的 META-INF/services 目录下创建一个以服务接口全限定名命名的文件。这个文件的内容就是实现类的全限定名,可以有多个实现类,每行一个。

  3. 服务发现:在应用程序中,通过 java.util.ServiceLoader 类来加载服务提供者的具体实现。ServiceLoader 会查找 classpath 下所有 META-INF/services 目录下的配置文件,并根据文件中的类名实例化具体的实现类。

示例:

  1. 定义服务接口:创建一个接口,如 MyService
public interface MyService {void doSomething();
}
  1. 实现服务接口:创建该接口的一个或多个实现类,如 MyServiceImpl1MyServiceImpl2
public class MyServiceImpl1 implements MyService {@Overridepublic void doSomething() {System.out.println("MyServiceImpl1 is doing something.");}
}public class MyServiceImpl2 implements MyService {@Overridepublic void doSomething() {System.out.println("MyServiceImpl2 is doing something.");}
}
  1. 配置服务提供者:在实现类的 jar 包的 META-INF/services 目录下创建一个名为 com.example.MyService 的文件(假设接口的全限定名为 com.example.MyService),文件内容分别写入实现类的全限定名。
com.example.MyServiceImpl1
com.example.MyServiceImpl2
  1. 使用 ServiceLoader 加载服务:在客户端代码中使用 ServiceLoader 加载并使用服务。
public class SpiClient {public static void main(String[] args) {ServiceLoader<MyService> loader = ServiceLoader.load(MyService.class);for (MyService service : loader) {service.doSomething();}}
}

运行 SpiClient 类,会依次打印出 MyServiceImpl1MyServiceImpl2 的输出,表明这两个服务提供者都被成功加载并执行了。

注意事项:

  • SPI 机制默认是懒加载,即首次迭代 ServiceLoader 的迭代器时才加载服务实现类。
  • SPI 加载过程是线程安全的,但实例化服务提供者不是,如果实例化过程需要并发控制,需要自行处理。
  • 由于 SPI 的实现是基于 classpath 扫描,因此它不适合动态加载服务实现,特别是在容器环境中。

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

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

相关文章

nexus搭建npm前端项目的私服

一、为什么要搭建私库 节省外网带宽加速maven构建部署第三方构件&#xff08;特别是无法从公共仓库下载的构件&#xff09;提高稳定性&#xff08;内网部署&#xff0c;更少地依赖外网&#xff09;降低中央仓库的负荷 构件&#xff0c;好比我们的藏书&#xff0c;去书店或商城…

深度学习——TensorBoard的使用

官方文档torch.utils.tensorboard — PyTorch 2.3 documentation TensorBoard简介 TensorBoard是一个可视化工具&#xff0c;它可以用来展示网络图、张量的指标变化、张量的分布情况等。特别是在训练网络的时候&#xff0c;我们可以设置不同的参数&#xff08;比如&#xff1…

【kubernetes】探索k8s集群的pod控制器详解(Deployment、StatefulSet、DaemonSet、Job、CronJob)

目录 一、Pod控制器及其功用 二、pod控制器有多种类型 2.1ReplicaSet 2.1.1ReplicaSet主要三个组件组成 2.2Deployment 2.3DaemonSet 2.4StatefulSet 2.5Job 2.6Cronjob 三、Pod与控制器之间的关系 3.1Deployment 3.2SatefulSet 3.2.1StatefulSet三个组件 3.2.2为…

为什么4个二进制位表示1个16进制位

为什么4个二进制位表示1个16进制位呢&#xff1f;首先需要了解二进制和十六进制分别是怎么样的。 1.二进制&#xff08;Binary&#xff09; 二进制就是只有2个数字的意思&#xff0c;这两个数字分别是0和1。如果我现在只有一个二进制数&#xff0c;那么这个二进制数只可能有两…

力扣 54.螺旋矩阵

题目描述&#xff1a; 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5]示例 2&#xff1a; 输入&#…

什么是Spark RDD?(RDD的介绍与创建)

什么是Spark RDD&#xff1f;(RDD的介绍与创建) 一、RDD介绍 1、特点2、RDD的存储和指向3、RDD与DAG4、RDD的特性5、RDD分区6、RDD操作类型 二、RDD创建 1、引入必要的 Spark 库2、配置 Spark3、RDD创建4、示例代码 一、RDD介绍 RDD: 弹性分布式数据集&#xff08;Resilient…

【ARMv7-A】——CP15 协处理器

文章目录 CP15 协处理器指令格式MCR 示例MRC 示例寄存器C0 identification registersC1 system control registersC2 memory protection and control registersC3 memory protection and control registersC4 Not usedC5 Memory system fault registers

【PCB]射频电路pcb设计

学习改变命运&#xff0c;技能成就未来&#xff01;❤~~ 1射频信号的基础知识及工作原理介绍 射频的基础知识介绍 2射频板PCB的布局要求 3射频板布局要求 4屏蔽帐设计 5射频板的层叠阻抗设计 6射频板的PCB布线原则 7射频板的PCB布线要求 8射频板的设计实战

鸿蒙Ability Kit(程序框架服务)【应用上下文Context】

应用上下文Context 概述 [Context]是应用中对象的上下文&#xff0c;其提供了应用的一些基础信息&#xff0c;例如resourceManager&#xff08;资源管理&#xff09;、applicationInfo&#xff08;当前应用信息&#xff09;、dir&#xff08;应用文件路径&#xff09;、area&…

Vue 实现的精彩动画效果

在 Vue 开发中&#xff0c;我们可以利用<transition>组件来打造各种令人惊艳的动画效果。下面来详细看看这些有趣的动画效果及其实现代码。 一、缩放类效果 zoom-in&#xff08;整体放大进入&#xff09; <template><div><button click"isShow ! …

10个令人惊叹的Python自动化脚本

大家好&#xff0c;Python凭借其简单和通用性&#xff0c;能够为解决每天重复同样的工作提供最佳方案。本文将介绍10个Python自动化脚本&#xff0c;可以帮助自动化完成任务&#xff0c;提高工作效率&#xff0c;它们可以成为项目运行中的便捷工具&#xff0c;可以收藏这些脚本…

AI办公自动化:用kimi批量提取音频中的标题并重命名

很多音频文件&#xff0c;文件名很乱&#xff0c;需要根据音频信息中的标题聪明吗 在kimi中输入提示词&#xff1a; 你是一个Python编程专家&#xff0c;一步步的思考&#xff0c;完成以下脚本的撰写&#xff1a; 打开文件夹&#xff1a;E:\有声\a16z播客 读取里面所有的mp3格…

ARM的工作模式

ARM的几种工作模式 User : 非特权模式&#xff0c;大部分任务执行在这种模式 FIQ : 当一个高优先级&#xff08;fast) 中断产生时将会进入这种模式IRQ : 当一个低优先级&#xff08;normal) 中断产生时将会进入这种模式 Supervisor&#xff08;SVC&#xff09; : 当复位或软中断…

GPT-4 Turbo 和 GPT-4 的区别

引言 人工智能&#xff08;AI&#xff09;领域的发展日新月异&#xff0c;OpenAI 的 GPT 系列模型一直是这一领域的佼佼者。GPT-4 和 GPT-4 Turbo 是目前市场上最先进的语言模型之一。本文将详细探讨 GPT-4 和 GPT-4 Turbo 之间的区别&#xff0c;以帮助用户更好地理解和选择适…

vue3中 window绑定scroll事件滚动页面获取不到e.target.scrollTop

遇到的问题 vue3项目 onMounted(() > {window.addEventListener(scroll, (e) > {console.log(e.target.scrollTop)}) })想要监听页面中的滚动&#xff0c;然后获取滚动距离实现一些功能&#xff0c;发现event参数中获取不到e.target.scrollTop&#xff08;印象中以前使…

React项目目录结构与组件基础结构

在React中开发项目并扩展组件时&#xff0c;一个清晰合理的目录结构是至关重要的。它不仅可以帮助你更好地组织代码&#xff0c;还能提高项目的可维护性和扩展性。下面是一个基本的React项目目录结构大纲&#xff0c;你可以根据自己的项目需求进行调整&#xff1a; my-app/ ├…

python 编写登录界面

import tkinter as tk from tkinter import messagebox def on_login(): username username_entry.get() password password_entry.get() # 这里只是模拟验证&#xff0c;实际中应从数据库验证 if username "admin" and password "password&quo…

【数据库初阶】SQL--DML

文章目录 DML1. 基本介绍2. 添加数据3. 修改数据4. 删除数据 更多数据库MySQL系统内容就在以下专栏&#xff1a; 专栏链接&#xff1a;数据库MySQL DML 1. 基本介绍 DML英文全称是Data Mainipulation Language&#xff08;数据操作语言&#xff09;&#xff0c;用来对数据库中…

面试被问准备多久要孩子?这样回答

听说有人面试被问到多久要孩子的问题&#xff0c;当时觉得很尴尬&#xff0c;不知如何回答&#xff0c;怕回答的不好不被录用&#xff0c;其实你可以这样回答&#xff0c;让面试官心满意足。 A 面试官&#xff1a;结婚了吗&#xff1f; 我&#xff1a;结婚了 面试官&#xff1…

Vuforia AR篇(六)— Mid Air 半空识别

目录 前言一、什么是Mid Air&#xff1f;二、使用步骤三、示例代码四、效果 前言 增强现实&#xff08;AR&#xff09;技术正在改变我们与数字世界的互动方式。Vuforia作为先进的AR开发平台&#xff0c;提供了多种工具来创造引人入胜的AR体验。其中&#xff0c;Mid Air功能以其…