Java SPI 机制实现解耦与本地化

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 机制实现解耦与本地化 

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,845评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,742评论 18 399
  • (一)Java部分 1、列举出JAVA中6个比较常用的包【天威诚信面试题】 【参考答案】 java.lang;ja...
    独云阅读 7,136评论 0 62
  • 20161112《加油,小川!》 最近迷上早上做养生,静静的躺在床上,全身一个部位,一个部位地做。 昨晚拖拖拉拉到...
    一棵樹阅读 228评论 2 1
  • 每个人都会把自己扮演各种的角色,生活中的,工作的,家人眼中的,朋友眼中的,我们都想把每一个角色做好,却都好像又没有...
    小2货阅读 531评论 0 1