当前位置: 首页 > news >正文

Java的SPI机制与实例

Java的SPI机制与实例

是什么?

SPI是一种JDK内置的服务提供发现的机制,能够启动框架扩展和替换组件,主要是被框架的开发人员使用,比如java.sql。Driver接口。Java机制的核心思想就是将装配的控制权转移到Java之外,核心思想是解耦。

怎么用?

当服务提供一个接口服务之后,加载需要再classpath的META-INF/services目录创建一个以服务接口全限定性类名的文件,在文件中配置具体的服务实现。
JDK中查找服务的实现的工具类是:java.util.ServiceLoader。通过这个接口加载具体的实现类,执行相应的方法。

实例

1、首先定义一个接口

package SPI;import java.util.List;public interface Search {public List<String> searchDoc(String keyword);
}

2、实现接口,这个就是具体的服务

package SPI;import java.util.List;public class FileSearch implements Search{@Overridepublic List<String> searchDoc(String keyword) {System.out.println("文件搜索 "+keyword);return null;}
}
package SPI;import java.util.List;public class DatabaseSearch implements Search{@Overridepublic List<String> searchDoc(String keyword) {System.out.println("数据搜索 "+keyword);return null;}
}

3、在META-INF/service中定义这个接口,注意文件时无格式的,名称需要为接口的全限定性名称
文件名称:SPI.Search
文件内容
SPI.FileSearch
SPI.DatabaseSearch
4、测试代码

package SPI;import java.util.Iterator;
import java.util.ServiceLoader;public class TestCase {public static void main(String[] args) {ServiceLoader<Search> s = ServiceLoader.load(Search.class);Iterator<Search> iterator = s.iterator();while (iterator.hasNext()) {Search search =  iterator.next();search.searchDoc("hello world");}}
}

结果:
文件搜索 hello world
数据搜索 hello world

Process finished with exit code 0
至此就实现了一个SPI的调用

缺点

通过上面的解析,可以发现,我们使用SPI机制的缺陷:不能按需加载,需要遍历所有的实现,并实例化,然后在循环中才能找到我们需要的实现。
如果不想用某些实现类,或者某些类实例化很耗时,它也被载入并实例化了,这就造成了浪费。
获取某个实现类的方式不够灵活,只能通过 Iterator 形式获取,不能根据某个参数来获取对应的实现类。多个并发多线程使用 ServiceLoader 类的实例是不安全的。

但是这些问题在dubbo得到了解决,需要看下这块代码

相关文章:

  • C语言内存函数详解
  • 停车场车辆统计C卷(JavaPythonC++Node.jsC语言)
  • 如何关闭 Visual Studio 双击异常高亮
  • 基于高德地图JS API实现Vue地图选点组件
  • JavaSE-----认识异常【详解】
  • 鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:Tabs)
  • 【ArcGISPro】道路数据下载并使用
  • 系统设计学习(四)海量数据
  • UGUI Text 重写Spacing字体间距
  • 面试经典-24-加油站
  • 【Linux】Shell编程【二】
  • JDK21虚拟线程缺陷总结
  • 某赛通电子文档安全管理系统 DecryptApplication 任意文件读取漏洞复现
  • 移远通信亮相AWE 2024,以科技力量推动智能家居产业加速发展
  • python爬虫实战——小红书
  • 【Redis学习笔记】2018-06-28 redis命令源码学习1
  • co模块的前端实现
  • express如何解决request entity too large问题
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • js ES6 求数组的交集,并集,还有差集
  • Promise初体验
  • React组件设计模式(一)
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • 创建一个Struts2项目maven 方式
  • 当SetTimeout遇到了字符串
  • 经典排序算法及其 Java 实现
  • 入门级的git使用指北
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • #1014 : Trie树
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • #我与虚拟机的故事#连载20:周志明虚拟机第 3 版:到底值不值得买?
  • $GOPATH/go.mod exists but should not goland
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • ( 用例图)定义了系统的功能需求,它是从系统的外部看系统功能,并不描述系统内部对功能的具体实现
  • (AngularJS)Angular 控制器之间通信初探
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (强烈推荐)移动端音视频从零到上手(下)
  • (三)elasticsearch 源码之启动流程分析
  • (四)【Jmeter】 JMeter的界面布局与组件概述
  • (转)setTimeout 和 setInterval 的区别
  • .net php 通信,flash与asp/php/asp.net通信的方法
  • .NET 发展历程
  • .net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池
  • .NET学习教程二——.net基础定义+VS常用设置
  • .one4-V-XXXXXXXX勒索病毒数据怎么处理|数据解密恢复
  • .pop ----remove 删除
  • @AliasFor注解
  • @JsonSerialize注解的使用
  • [<MySQL优化总结>]
  • [AIR] NativeExtension在IOS下的开发实例 --- IOS项目的创建 (一)
  • [Android]Android开发入门之HelloWorld