Java Service Provider Interface

Java Service Provider Interface_第1张图片

1.概述

Java 6 has introduced a feature for discovering and loading implementations matching a given interface: Service Provider Interface (SPI).

SPI是JDK1.6引入的特性,用于发现和加载与给定接口相匹配的实现类,实现了服务提供方和使用方的解耦,并且可以实现动态加载。

2.Java SPI的定义和术语

Service(服务)

一组众所周知的编程接口和类,提供对某些特定应用程序功能或特性的访问。

A well-known set of programming interfaces and classes that provide access to some specific application functionality or feature.

Service Provider Interface(服务提供的接口)

作为服务的代理或端点的接口或抽象类。

An interface or abstract class that acts as a proxy or an endpoint to the service.

Service Provider(具体提供的服务)

SPI的特定实现。服务提供者包含一个或多个实现或扩展服务类型的具体类
服务提供者通过提供者配置文件进行配置和标识,我们将该配置文件放在资源目录META-INF/services中。文件名是SPI的全限定类名,其内容是SPI实现的全限定类名。
服务提供者以扩展名的形式安装,扩展名是一个jar文件,我们把它放在应用程序类路径、Java扩展类路径或用户定义的类路径中。

A specific implementation of the SPI. The Service Provider contains one or more concrete classes that implement or extend the service type.

A Service Provider is configured and identified through a provider configuration file which we put in the resource directory META-INF/services. The file name is the fully-qualified name of the SPI and its content is the fully-qualified name of the SPI implementation.

The Service Provider is installed in the form of extensions, a jar file which we place in the application classpath, the Java extension classpath or the user-defined classpath.

ServiceLoader(服务加载器)

SPI的核心是ServiceLoader类,它的作用是惰性地发现和加载实现。它使用上下文类路径来定位提供程序实现,并将它们放在内部缓存中。

At the heart of the SPI is the ServiceLoader class. This has the role of discovering and loading implementations lazily. It uses the context classpath to locate provider implementations and put them in an internal cache.

3.Java生态系统中的SPI示例

Java提供了很多的SPI机制的实现。下面是服务提供者接口及其提供的服务的一些示例,比较经典的就是Driver,还有SLF4J,有兴趣的可以自己去了解下。

  • CurrencyNameProvider: provides localized currency symbols for the Currency class.
  • LocaleNameProvider: provides localized names for the Locale class.
  • TimeZoneNameProvider: provides localized time zone names for the TimeZone class.
  • DateFormatProvider: provides date and time formats for a specified locale.
  • NumberFormatProvider: provides monetary, integer and percentage values for the NumberFormat class.
  • Driver: as of version 4.0, the JDBC API supports the SPI pattern. Older versions uses the Class.forName() method to load drivers.
  • PersistenceProvider: provides the implementation of the JPA API.
  • JsonProvider: provides JSON processing objects.
  • JsonbProvider: provides JSON binding objects.
  • Extension: provides extensions for the CDI container.
  • ConfigSourceProvider: provides a source for retrieving configuration properties.

4.Java SPI Demo

demo分为4个module,分别为exchange-rate-api、exchange-rate-impl1、exchange-rate-impl2、exchange-rate-app。

exchange-rate-api  定义服务接口的api module

exchange-rate-impl1  服务接口的实现1 module

exchange-rate-impl2  服务接口的实现2 module

exchange-rate-app  模拟对外提供服务的module

exchange-rate-api 

Definition: Service Interface

Java Service Provider Interface_第2张图片

Definition: Service Provider Interface

Java Service Provider Interface_第3张图片

 Definition: ServiceLoader(可以定义在api module,也可以定义在appmodule)

Java Service Provider Interface_第4张图片

exchange-rate-impl1

Definition: Service Provider

Java Service Provider Interface_第5张图片

Java Service Provider Interface_第6张图片

Java Service Provider Interface_第7张图片

exchange-rate-impl2

Definition: Service Provider

Java Service Provider Interface_第8张图片

Java Service Provider Interface_第9张图片

 实体Bean

Java Service Provider Interface_第10张图片

exchange-rate-app

Java Service Provider Interface_第11张图片

在exchange-rate-app的pom.xml中,引入exchange-rate-impl1,运行结果如下:

在exchange-rate-app的pom.xml中,引入exchange-rate-impl2,运行结果如下:

5.结论

从上面的demo可以看出,利用Java SPI可以创建易于拓展或替换的模块。

SPI对比写死实现类的方法:去除了硬编码,降低了代码的耦合度,拓展性更高 。

SPI对比IOC自动注入:自动注入依赖IOC容器,需要配置包扫描; SPI只需要创建文件放到WEB-INF/services路径下就可以完成实现类注入,提供与使用的解耦,拓展性更高,并且可以实现动态加载。

6.参考网址

Java Service Provider Interface(英文版)

你可能感兴趣的:(java基础,java,开发语言)