Java SPI机制概述

先给出结论:“Java的SPI是一种服务发现机制,用于约定接口和动态发现实现类,体现了分层解耦的思想”。

Java的SPI机制常用于框架扩展或组件替换,最常见的Java SPI应用就是JDBC Driver,JDK提供了java.sql.Driver接口,却将具体的实现交给了相应的数据库驱动,比如:在mysql-connector-java-6.0.6.jar文件中可以看到一个遵循Java SPI机制的文件META-INF/services/java.sql.Driver,并且在该文件中定义了具体的驱动实现类完整限定名称:com.mysql.cj.jdbc.Driver

驱动实现类com.mysql.cj.jdbc.Driver实现了JDK提供的java.sql.Driver接口。

关于Java原生SPI机制的说明详见:Introduction to the Service Provider Interfaces

如何实践Java SPI机制

应用Java SPI机制分为四步:

第一步: 约定接口。

package org.chench.extra.java.spi;
public interface HelloSPI {
void sayHello();
}

第二步: 编写接口实现类。

package org.chench.extra.java.spi;
public class ImageHello implements HelloSPI {
@Override
public void sayHello() {
System.out.println("Image Hello");
}
}

第三步: 在实现类所在的jar包路径META-INF/services下创建一个以“接口完整限定名”命名的描述文件,文件内容为“实现类的完整限定名”(可以是包含多行,每一行是一个实现类的完整限定名)。

如:创建文件META-INF/services/org.chench.extra.java.spi.HelloSPI,内容为:org.chench.extra.java.spi.ImageHello

第四步: 使用Java SPI机制动态加载实现类。

public class SPISample {
public static void main(String[] args) {
// Java SPI机制使用ServiceLoader动态加载实现类
ServiceLoader<HelloSPI> loader = ServiceLoader.load(HelloSPI.class);
Iterator<HelloSPI> iterator = loader.iterator();
while (iterator.hasNext()) {
iterator.next().sayHello();
}
}
}

输出:

Image Hello

如上所示,在Java SPI机制的应用中接口实现类是完全分开的(在不用的jar文件中),所以需要在实现类所在的jar文件中包含一个描述文件。

通常来讲,Java的SPI机制常用于框架中实现功能扩展或替换,即:接口定义和使用ServiceLoader动态加载实现类是在框架代码中,而接口实现类以及描述文件是在扩展代码中,它们分布在不同的jar文件。

实际上,在分布式服务框架Dubbo中也提供了类似于Java原生SPI的扩展机制,详见:自定义扩展

Java原生SPI机制的不足

ServiceLoader类的应用及实现来看,存在一些缺点和不足:

  1. 原生的Java SPI机制只能通过迭代器访问实现类,这样会加载所有在描述文件中的实现类,无法按需加载将造成内存资源浪费。
  2. 多个并发线程使用ServiceLoader示例时不是线程安全的。

为了弥补Java原生SPI机制的不足,Dubbo框架提供了自己的SPI扩展机制,具体使用详见:自定义扩展

【参考】

深入理解 Java 中 SPI 机制

搞懂dubbo的SPI扩展机制

Dubbo 扩展设计理念

Java的SPI机制实践的更多相关文章

  1. java 的SPI机制

    今天看到spring mvc 使用Java Validation Api(JSR-303)进行校验,需要加载一个 其具体实现(比如Hibernate Validator), 本来没有什么问题,但是突然 ...

  2. Java的SPI机制与简单的示例

    一.SPI机制 这里先说下SPI的一个概念,SPI英文为Service Provider Interface单从字面可以理解为Service提供者接口,正如从SPI的名字去理解SPI就是Service ...

  3. Java之SPI机制

    之前开阿里的HSF框架,里面用到了Java的SPI机制,今天闲暇的时候去了解了一下,通过写博客来记录一下 SPI的全名为Service Provider Interface,我对于该机制的理解是为接口 ...

  4. Java的Spi机制心得

    Java spi : 是Java EE 给服务供应商提供的接口,供应商遵循接口契约提供自己的实现.. 简单来讲就是为某个接口寻找服务实现的机制. 在看JDBC源码当看到DriverManage.get ...

  5. 深入理解 Java 中 SPI 机制

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/vpy5DJ-hhn0iOyp747oL5A作者:姜柱 SPI(Service Provider ...

  6. JAVA中SPI机制

    之前研究dubbo的时候就很好奇,里面各种扩展机制,期间也看过很多关于SPI的机制,今日有缘再度看到有文章总结,故记录一下, 首先了解一下 JAVA中SPI简单的用法 可参考这篇文章,https:// ...

  7. Java的SPI机制

    目录 1. 什么是SPI 2. 为什么要使用SPI 3. 关于策略模式和SPI的几点区别 4. 使用介绍或者说约定 4.1 首先介绍几个名词 4.2 约定 5. 具体的demo实现 5.1 创建服务提 ...

  8. Java 的 SPI 机制

    什么是SPI机制? SPI机制( Service Provider Interface)是Java的一种服务发现机制,为了方便应用扩展.那什么是服务发现机制?简单来说,就是你定义了一个接口,但是不提供 ...

  9. Java CAS同步机制 实践应用

    利用CAS实现原子操作类AtomicInteger (这是自定义的AtomicInteger:java有封装好的原子操作AtomicInteger类): class AtomicInteger { p ...

  10. 你应该了解的 Java SPI 机制

    前言 不知大家现在有没有去公司复工,我已经在家办公将近 3 周了,同时也在家呆了一个多月:还好工作并没有受到任何影响,我个人一直觉得远程工作和 IT 行业是非常契合的,这段时间的工作效率甚至比在办公室 ...

随机推荐

  1. Python学习之四_部分battery的学习

    Python学习之四_部分battery的学习 CentOS升级pip的方法 yum install python3 之后, 一般centos的版本都很低, 有时候很多module 是无法安装的. 一 ...

  2. [转帖]Centos7 nginx访问日志文件割接

    一.yum安装nginx 二.各文件路径( /etc/nginx/nginx.conf) 1.访问日志路径:access_log /var/log/nginx/access.log main; 2.p ...

  3. 【转帖】在ECS上配置skywalking-nginx-lua

    https://help.aliyun.com/document_detail/197660.html 此处以在CentOS 7.0上的操作为例. 配置Lua运行环境. 安装工具库.   yum in ...

  4. [转帖]开源软件项目中BSD、MIT许可证合规问题探析

    https://www.allbrightlaw.com/CN/10475/3be2369275d19e9e.aspx   [摘要]本文将探析BSD开源许可证(Berkeley Software Di ...

  5. [转帖]一起来体验96核心、192线程CPU——第四代AMD EPYC处理器独家测试

    http://k.sina.com.cn/article_1882475282_70344b12027010s1x.html 与第三代EPYC 7003系列处理器相比,新一代EPYC 9004系列处理 ...

  6. 使用systemd管理多nginx服务以及单nginx服务实现多vhost访问的操作步骤

    背景 nginx是开源的web服务器, 性能与可配置性和插件做的非常完善. 可以使用简单的命令拉起来nginx进行服务提供,但是有时候需要使用keepalive等软件实现保活,以及实现开启启动等,比较 ...

  7. 总结: Redis 查看key大小的简单总结

    Redis 查看key大小的简单总结 第一步: 安装rdbtools 吐槽一下 python 非常不熟悉 第一步 安装epel以及python等工具 yum install epel-release ...

  8. 通过Environment获取属性文件的值,竟然会调用到JNDI服务!!!

    一.背景介绍 某应用在压测过程机器cpu使用率超过80%,通过在线诊断工具进行CPU采样生成的火焰图,看到程序中频繁调用environment.getProperty()获取属性值,而其内部调用了Jn ...

  9. 【k哥爬虫普法】Python程序员爬取视频资源13万部,一分钱没挣,获刑2年!

    我国目前并未出台专门针对网络爬虫技术的法律规范,但在司法实践中,相关判决已屡见不鲜,K 哥特设了"K哥爬虫普法"专栏,本栏目通过对真实案例的分析,旨在提高广大爬虫工程师的法律意识, ...

  10. Git - 关联远程仓库以及同时使用Lab和Hub

    更新一下,感觉有更简单的方式 就比如你git config 的 全局的name和email是lab的 那就clone github上的项目然后设置局部的name和email就行了 ********** ...