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. 报表工具FastReport VCL 最新版发布!

    新功能 为主要包类添加了类引用 在报表设计器中添加了SQL编辑器的自定义 为TfrxReport的操作添加了延迟的命令池:PrepareReport,ShowReport,LoadFrom.可以调用R ...

  2. 编程源自生活:抽象 -> 生活中的洗头问题

    设计背景: 我:头上的油揩给了手,手接触洗手液.洗手液伤头皮,这样头皮就不会和洗手液接触了. 具体执行过程描述: 1.手揩油  ->  2.取液体  3.->洗手   我:这是什么设计模式 ...

  3. 为cmd中的命令添加别名,以解决java:错误: 编码 GBK 的不可映射字符 (0xAF)

    使用sublineText3编写了java代码,通过cmd javac编译 提示 错误:编码GBK的不可映射字符 解决方法 使用javac -encoding UTF-8 Person.java 结果 ...

  4. 一个漂亮的JavaScript“警告”替代品

    下载 一个漂亮的JavaScript"警告"替代品 安装 $ npm安装-节省sweetalert 使用 从"sweetalert"进口swal; 横波测井(& ...

  5. MySQL数据备份脚本

    #!/bin/bash ############################# # time:20191210 # fage trainning ######################### ...

  6. 最新最最最简单的Axure傻瓜式破解版教程(带下载地址)

    Axure 破解版下载 下载地址在文章末尾 Axure是什么? Axure RP是一款专业的快速原型设计工具.Axure(发音:Ack-sure),代表美国Axure公司:RP则是Rapid Prot ...

  7. day28 Pyhton 面向对象 继承

    1.昨日回顾 类的命名空间 静态属性\动态属性(方法) 对象的命名空间 #对象的属性 #类指针:对象能够通过这个类指针找到类 #静态属性:属于类,多个对象共享这个资源 #尽量用类名来操作静态属性 #对 ...

  8. day26 Pyhton 面向对象复习

    一 class 类名(): pass 对象 object 对象 = 类名() class Person: pass print(Person)#<class '__main__.Person'& ...

  9. logback.xml demo

    如何关闭 org.apache.zookeeper.clientcnxn 的(控制台大量输出)debug 日志 1.在项目resources路径下新建 logback.xml 2.然后把下面的代码co ...

  10. js拖拽上传 文件上传之拖拽上传

    由于项目需要上传文件到服务器,于是便在文件上传的基础上增加了拖拽上传.拖拽上传当然属于文件上传的一部分,只不过在文件上传的基础上增加了拖拽的界面,主要在于前台的交互, 从拖拽的文件中获取文件列表然后调 ...