SPI 是 Java 提供的一种服务加载方式,全名为 Service Provider Interface,可以避免在 Java 代码中写死服务的提供者,而是通过 SPI 服务加载机制进行服务的注册和发现。通过这种方式,可以基于接口编程,实现多个模块的解耦。

SPI 机制实现解耦

如下的示例展示了通过 ServiceLoader 类加载指定接口的所有服务提供者并进行调用的简单实现。

1、定义接口 test.DirMonitor,包含一个方法 start();

2、实现接口 test.DirMonitor,定义两个实现类 test.ObserverMonitor 和 test.LoopMonitor;

3、设置接口的实现类列表。创建目录 META-INF/services/,新建文件 test.DirMonitor,内容如下:

test.ObserverMonitor

test.LoopMonitor

4、在程序中通过 ServiceLoader 类加载 test.DirMonitor 接口的实现类,并遍历所有实现类,调用 start() 方法;

从上面的示例可以看出,在代码中仅仅使用到了接口 test.DirMonitor,并没有在代码中使用到具体实现类。通过这种方法,可以实现解耦,接口与实现类可以由不同的开发人员实现,编译到不同的 jar 包中,甚至实现插件的定义与开发。

spi 包的本地化扩展

java.util.spi 包提供了一些抽象类,可以用于扩展 Java 的本地化服务。本地化 SPI 的使用方法与 ServiceLoader 的 SPI 稍有不同,本地化 SPI 的实现需要打包成 jar 包后,放置于运行的 jre/lib/ext 目录下方能生效。

java.util.spi 包提供的抽象类如下所示:

CalendarDataProvider:为 java.util.Calendar 类的参数提供本地化数据的服务提供者的抽象类;

CalendarNameProvider:为 java.util.Calendar 类的字段提供本地化名称的服务提供者的抽象类;

CurrencyNameProvider:为 java.util.Currency 提供本地化货币符号名称的服务提供者的抽象类;

LocaleNameProvider:为 java.util.Locale 类提供本地化名称的服务提供者的抽象类;

LocaleServiceProvider:其他服务提供者抽象类的基类;

ResourceBundleControlProvider:服务接口,用于提供 java.util.ResourceBundle.Control 的实现类;

TimeZoneNameProvider:为 java.util.TimeZone 提供本地化时区的服务提供者的抽象类。

以 CalendarDataProvider 为例,该抽象类用于实现本地化的日历数据。在下面的例子中,CalendarDataProviderSPI 类设置了每周的第一天为 3,一年中第一周所需的最少天数为 6。

按照 SPI 的要求,在 META-INF/services/ 下建立 java.util.spi.CalendarDataProvider 文件,并写入 testspi.CalendarDataProviderSPI。打包为 jar 后,放置于 jre/lib/ext 目录后,执行下面的代码,则打印的数字分别为 3 和 6,而不再是默认的 1 和 1。

总结

Java 通过 SPI 机制为我们提供了一种服务发现机制。通过在 META-INF/services/ 目录下创建以接口全限定名为名称的文件,并在文件中每行写入一个服务提供者的全限定名,Java 可以发现并创建服务提供者的实例。

通过 ServiceLoader 我们可以获取指定接口的所有服务提供者,并实现接口调用与服务提供者的解耦。通过实现 spi 包的抽象接口,并放置于 jre/lib/ext 目录下,可以实现 Java 的本地化。

原文地址:Java SPI 机制实现解耦与本地化

Java SPI 机制实现解耦与本地化的更多相关文章

  1. JDK源码解析之Java SPI机制

    1. spi 是什么 SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件. 系统设计的各个抽象,往往 ...

  2. Java SPI机制实战详解及源码分析

    背景介绍 提起SPI机制,可能很多人不太熟悉,它是由JDK直接提供的,全称为:Service Provider Interface.而在平时的使用过程中也很少遇到,但如果你阅读一些框架的源码时,会发现 ...

  3. 组件化框架设计之Java SPI机制(三)

    阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 本篇文章将从深入理解java SPI机制来介绍组件化框架设计: ...

  4. Java spi机制浅谈

    最近看到公司的一些框架和之前看到的开源的一些框架的一些服务发现和接入都采用了java的spi机制. 所以简单的总结下java spi机制的思想. 我们系统里抽象的各个模块,往往有很多不同的实现方案,比 ...

  5. 聊聊Java SPI机制

    一.Java SPI机制 SPI(Service Provider Interface)是JDK内置的服务发现机制,用在不同模块间通过接口调用服务,避免对具体服务服务接口具体实现类的耦合.比如JDBC ...

  6. Java SPI机制详解

    Java SPI机制详解 1.什么是SPI? SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制.SPI是一种动态替换发现的机制, 比如有个 ...

  7. Java SPI机制和使用示例

    JAVA SPI 简介 SPI 是 Java 提供的一种服务加载方式,全名为 Service Provider Interface.根据 Java 的 SPI 规范,我们可以定义一个服务接口,具体的实 ...

  8. Java SPI机制,你了解过吗?

    Life moves pretty fast,if you don't stop and look around once in a while,you will miss it 为什么需要SPI? ...

  9. java SPI机制

    1. SPI是Service Provider Interfaces的简称.根据Java的SPI规范,我们可以定义一个服务接口,具体的实现由对应的实现者去提供,即Service Provider(服务 ...

随机推荐

  1. MMC & SD 发展历史

    一.概述 MMC 卡和 SD 卡都是基于 Nand Flash 技术的移动存储卡. MMC(MultiMediaCard) 卡于 1997 年由西门子和 Sandisk 推出,SD (Secure D ...

  2. eureka源码--服务的注册、服务续约、服务发现、服务下线、服务剔除、定时任务以及自定义注册中心的思路

    微服务注册后,在注册中心的注册表结构是一个map: ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>& ...

  3. Centos-关机重启

    为何要使用命令进行关机重启? linux系统中的各个进程携带着各种数据,强制关机会照成数据混乱而丢失数据,甚至可能损坏硬件,所以我们需要更加安全的关机和重启方式 关机重启相关命令,需要root用户才能 ...

  4. 为 MaixPy 加入软 I2C 接口(移植 MicroPython 的 I2C)

    起因 本文的重心为讲解如何为一款芯片移植和实现 micropython 的通用组件,但会顺带解释不同芯片的工作方式和特性. 国际惯例,先有起因,再谈问题的解决,所以记得上次总结的 关于 K210 Ma ...

  5. RT-Thread小知识点收集

  6. 【题解】[USACO09NOV]A Coin Game S

    Link \(\text{Solution:}\) 菜鸡自己想出来了状态设计,但是没有实现出来--菜死了 设\(dp[i][j]\)表示该选第\(i\)个,最多选\(j\)个的最优解.注意这里的定义仅 ...

  7. centos 7 安装docker 常用指令

    什么是docker l  使用最广泛的开源容器引擎 l  一种操作系统级的虚拟化技术 l  依赖于Linux内核特性:Namespace和Cgroups l  一个简单的应用程序打包工具 docker ...

  8. CAD& CG 2020 胡事民教授—开源框架Jittor的创新与探索

    题目:深度学习框架"计图"的创新与探索 报告人:胡事民 报告人简介:胡事民,清华大学计算机系教授,主要研究方向为计算机图形学.虚拟现实.智能信息处理和系统软件等. 报告简介:深度学 ...

  9. shell-批量修改文件名及扩展名多案例

    1. 功能描述如下表: 批量文件改名案例实战: 问题1:  创建测试数据 [root@1-241 tmp]# for i in `seq 6`;do touch stu_161226_${i}_fin ...

  10. ansible-命令使用说明

    1. ansible命令的使用说明 ansible 主机或组-m 模块名-a '模块参数' ansible参数 表示调用什么模块,使用模块的那些参数 • 主机和组,是在/etc/ansible/hos ...