Java SPI 代码示例

news2024/10/6 18:22:43

Java Service Provider Interface 是JDK自带的服务提供者接口又叫服务发现机制更是一种面向接口的设计思想。即JDK本身提供接口类, 第三方实现其接口,并作为jar包或其他方式注入到其中, 在运行时会被JDK ServiceLoader 发现并加载,自动调用实现类的方法。

1. 在本地测试SPI机制

本人使用类似日志记录组件, 项目一提供接口,由第三方(项目二)提供自定义日志实现类。tips: 一般影响力大的机构或组织才可以定义SPI接口 比如Java , SLF4J, Spring ~

JDK: Java21

  1. 在原有项目一(sample)创建测试类,以及接口文件
  2. 新建项目二(spitest) 提供多个实现类
  3. 最重要的:在spitestMETA-INF/services 文件夹下增加配置文件, 命名为 sample中接口类的全路径限定名
  4. 执行测试类,查看结果
1.1 项目一 测试类及接口
import java.util.ServiceLoader;

public class JdkSpi {
    public static void main(String[] args) {
        ServiceLoader<LoggerForSpiTest> spiTests = ServiceLoader.load(LoggerForSpiTest.class);
        spiTests.forEach( logger -> System.out.println(logger.log("hello ")));
    }
}

接口:

public interface LoggerForSpiTest {
    String log (String msg);
}

2.1 项目二 实现类

由于实现类需要引入此接口类LoggerForSpiTest, 因此打包时候可以去除掉接口类即可

实现类LoggerA

import com.jay.base.LoggerForSpiTest;

public class LoggerA implements LoggerForSpiTest {
    @Override
    public String log(String msg) {
        return msg + "i am LoggerA";
    }
}

实现类LoggerB

import com.jay.base.LoggerForSpiTest;

public class LoggerB implements LoggerForSpiTest {
    @Override
    public String log(String msg) {
        return msg + "i am LoggerB";
    }
}

3.1 项目二中添加配置文件

com.jay.spi.LoggerA
com.jay.spi.LoggerB

其中内容是 实现类的路径限定名, 由于我实现了两个Logger为了区分效果,实际可能只需要一个,例如mysql jdbc connector jar包中


其中jdk 提供了Driver接口类, 让第三方如 Mysql, Oracle, SqlServer 等实现其厂家自己的实现类.

4.1 打包项目二spitest为jar,导入到项目一sample

打包只用包含 spitest compile output即可,即 只需要spitest中自己写的代码的编译文件打成jar

导入成功后,打开jar只能看到三个文件即 LoggerA, LoggerB, 以及META-INF/services里面的配置文件

4.2 运行测试类JdkSpi.java

输出结果为:

hello i am LoggerA
hello i am LoggerB

2. FYI.

类似于我们使用的日志打印组件,代码会在ServiceLoader.load(LoggerForSpiTest.class) 方法中构造ServiceLoader对象, 而其是继承了Iterable接口,在代码spiTests.forEach( logger -> System.out.println(logger.log("hello "))); 中迭代去使用的时候去加载META-INF/services下的所有实现类 LoggerA, LoggerB至此本文不再扩展,会再次以新文章介绍。
`

 @CallerSensitive
    public static <S> ServiceLoader<S> load(Class<S> service) {  
        ClassLoader cl = Thread.currentThread().getContextClassLoader();  //获取当前类加载器
        return new ServiceLoader<>(Reflection.getCallerClass(), service, cl); // 构造ServiceLoader(调用类, 接口类, 类加载器)
    }

关于Reflection.getCallerClass()看到源码注释是会跳过所有反射的过程直达调用的地方,类似编码过程中发现报错我们可以通过一些IDE看到stack info 并看到最初调用的地方排查问题。由于本文不介绍反射,所以不宜继续扩展。

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

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

相关文章

锐捷VSU和M-LAG介绍

参考网站 堆叠、级联和集群的概念 什么是堆叠&#xff1f; 框式集群典型配置 RG-S6230[RG-S6501-48VS8CQ]系列交换机 RGOS 12.5(4)B1005版本 配置指南 总结 根据以上的几篇文章总结如下&#xff1a; 级联&#xff1a;简单&#xff0c;交换机相连就叫级联&#xff0c;跟搭…

SaaS 电商设计 (八) 直接就能用的一套商品池完整的设计方案(建议收藏)

目录 一.前言1.1 在哪些业务场景里使用1.2 一些名词搞懂他1.3 结合业务思考一下-业务or产品的意图 二.方案设计2.1 业务主流程2.2 一步步带你分析B端如何配置2.3 数据流2.3.1 ES 数据表建设2.3.2 核心商品池流程2.3.2.1 商品池B端维护流程2.3.2.2 商品池版本更新逻辑 2.4 核心代…

PySpark(三)RDD持久化、共享变量、Spark内核制度,Spark Shuffle

目录 RDD持久化 RDD 的数据是过程数据 RDD 缓存 RDD CheckPoint 共享变量 广播变量 累加器 Spark 内核调度 DAG DAG 的宽窄依赖和阶段划分 内存迭代计算 Spark是怎么做内存计算的? DAG的作用?Stage阶段划分的作用? Spark为什么比MapReduce快&#xff1f; Spar…

Java项目服务器部署

Java项目服务器部署 Tomocat Java项目进行云服务器部署 如果有需要比赛部署的同学也可以联系我&#xff0c;我后续还会对于这个专栏继续展开 1、云服务器选购 1.1 阿里云选购&#xff08;宝塔面板&#xff09; 1.2 端口放行 这里说的就是端口放行&#xff0c;后面一些访问比…

打造直播带货商城APP:源码开发技术全解析

直播带货商城APP的创新模式吸引了用户&#xff0c;提升销售业绩&#xff0c;已经成为了近期开发者讨论的热门话题。今天&#xff0c;小编将深入讲解如何打造一款功能强大的直播带货商城APP&#xff0c;着重分析源码开发技术&#xff0c;为开发者提供全方位的指导。 一、前期准…

电商推荐系统

此篇博客主要记录一下商品推荐系统的主要实现过程。 一、获取用户对商品的偏好值 代码实现 package zb.grms;import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configured; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.Doub…

docker自定义镜像并使用

写在前面 本文看下如何自定义镜像。 ik包从这里 下载。 1&#xff1a;自定义带有ik的es镜像 先看下目录结构&#xff1a; /opt/program/mychinese [rootlocalhost mychinese]# ll total 16 -rw-r--r-- 1 root root 1153 Feb 5 04:18 docker-compose.yaml -rw-rw-r-- 1 el…

2024智慧城市新纪元:引领未来,重塑都市生活

随着科技的飞速发展和数字化转型的不断深入&#xff0c;2024年智慧城市领域迎来了全新的发展格局。 这一年&#xff0c;智慧城市的建设更加注重人性化、可持续性和创新性&#xff0c;为城市居民带来了前所未有的便捷与舒适。以下将重点关注智慧城市的几个核心内容&#xff0c;…

Java设计模式-模板方法模式(14)

行为型模式 行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对…

【UE 材质】扇形材质

目录 效果 步骤 &#xff08;1&#xff09;控制扇形的弧宽度 &#xff08;2&#xff09;控制扇形的角度 &#xff08;3&#xff09;完整节点 效果 步骤 &#xff08;1&#xff09;控制扇形的弧宽度 创建一个材质&#xff0c;混合模式设置为“Additive”&#xff0c;着色…

代码随想录算法训练营DAY13 | 栈与队列 (3)

一、LeetCode 239 滑动窗口最大值 题目链接&#xff1a;239.滑动窗口最大值https://leetcode.cn/problems/sliding-window-maximum/ 思路&#xff1a;使用单调队列&#xff0c;只保存窗口中可能存在的最大值&#xff0c;从而降低时间复杂度。 public class MyQueue{Deque<I…

On the Spectral Bias of Neural Networks论文阅读

1. 摘要 众所周知&#xff0c;过度参数化的深度神经网络(DNNs)是一种表达能力极强的函数&#xff0c;它甚至可以以100%的训练精度记忆随机数据。这就提出了一个问题&#xff0c;为什么他们不能轻易地对真实数据进行拟合呢。为了回答这个问题&#xff0c;研究人员使用傅里叶分析…

mysql+node.js+html+js完整扫雷项目

一.下载 可以直接下载绑定资源&#xff0c; 也可以访问&#xff1a;克隆仓库&#xff1a;mine_clearance: mysqlnode.jshtmljs完整扫雷项目 (gitee.com) 二.运行sql数据文件 将mysql数据文件导入到本地 先在本地localhost里创建数据库 mine_clearance&#xff0c; 然后如图&…

编译原理本科课程 专题5 基于 SLR(1)分析的语义分析及中间代码生成程序设计

一、程序功能描述 本程序由C/C编写&#xff0c;实现了赋值语句语法制导生成四元式&#xff0c;并完成了语法分析和语义分析过程。 以专题 1 词法分析程序的输出为语法分析的输入&#xff0c;完成以下描述赋值语句 SLR(1)文法的语义分析及中间代码四元式的过程&#xff0c;实现…

进程和线程的区别详解

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f4d5;格言&#xff1a;那些在暗处执拗生长的花&#xff0c;终有一日会馥郁传香欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 进程 进程在系统中是如何管理的 进一步认识PCB 线程 能否一直增加线程数目来提高效率 进程和线程…

【240126】上海大学—调剂信息

上海大学 学校层级&#xff1a;211 调剂专业&#xff1a;081000 信息与通信工程 发布时间&#xff1a;2024.1.26 发布来源&#xff1a;网络发布 调剂要求&#xff1a;要求考数一英一且初试成绩在320分以上 来源说明 1、官方发布&#xff1a;学校官网、研招网 2、网络发布…

EOF和0区别

题目描述 KiKi学习了循环&#xff0c;BoBo老师给他出了一系列打印图案的练习&#xff0c;该任务是打印用“*”组成的X形图案。 输入描述&#xff1a; 多组输入&#xff0c;一个整数&#xff08;2~20&#xff09;&#xff0c;表示输出的行数&#xff0c;也表示组成“X”的反斜…

Architecture Lab:Part C【流水线通用原理/Y86-64的流水线实现/实现IIADDQ指令】

目录 任务描述 知识回顾 流水线通用原理 Y86-64流水线实现&#xff08;PIPE-与PIPE&#xff09; 开始实验 IIADDQ指令的添加 优化 ncopy.ys 仅用第四章知识&#xff0c;CEP11.55 8x1展开&#xff0c;CPE9.35 8x1展开2x1展开消除气泡&#xff0c;CPE8.10 流水线化通过…

在VM虚拟机上搭建MariaDB数据库服务器

例题&#xff1a;搭建MariaDB数据库服务器&#xff0c;并实现主主复制。 1.在二台服务器中分别MariaDB安装。 2.在二台服务器中分别配置my.cnf文件&#xff0c;开启log_bin。 3.在二台服务器中分别创建专用于数据库同步的用户replication_user&#xff0c;并授权SLAVE。&#x…

【DDD】学习笔记-数据分析模型

在 Eric Evans 提出领域驱动设计之前&#xff0c;对企业系统的分析设计多数采用数据模型驱动设计。如前所述&#xff0c;这种数据模型驱动设计就是站在数据的建模视角&#xff0c;逐步开展分析、设计与实现的建模过程。通过对数据的正确建模&#xff0c;设计人员就可以根据模型…