一、概述

Java 6提供了一个用于发现和加载指定接口实现的功能:服务提供者接口(Service Provider Interface)。

Java SPI 定义了四个主要的组件:Service、Service Provider Interface、Service Provider、ServiceLoader。

  • Service

Service(服务)是一组提供访问某些特定应用程序功能或特性的编程接口和类。

  • Service Provider Interface

Service Provider Interface(服务提供者接口)是一个作为服务代理的接口或抽象类。

Service(服务)和SPI(服务提供者接口)在Java生态系统中一起被称为 API。

  • Service Provider

Service Provider(服务提供者)是服务提供者接口(SPI)的特定实现,它包含一个或多个实现或扩展了服务的具体类。

服务提供者需要在META-INF/services目录下添加一个配置文件,文件名是服务提供者接口(SPI)的完全限定名称,文件内容是服务提供者接口(SPI)实现的完全限定名称。

  • ServiceLoader

ServiceLoader(服务加载器)是SPI的核心,具有延迟发现和加载实现的作用;它使用上下文类路径(context classpath)来查找服务提供者接口的实现并将它们放在内部缓存中。

Java提供了很多SPI,例如:java.sql.Driverjava.text.spi.DateFormatProvider等,如果JDK的实现不满足需求,则可以扩展或替换这些提供程序。

二、样例

1、服务提供者接口

  • 工程

hello-world-api:

<groupId>com.spi</groupId>
<artifactId>hello-world-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
  • 接口

HelloService:

package com.spi.api;

public interface HelloService {
	
	public void sayHello();
}

2、服务提供者

  • 工程

hello-world-impl:

<groupId>com.spi</groupId>
<artifactId>hello-world-impl</artifactId>
<version>0.0.1-SNAPSHOT</version>

<dependencies>
	<dependency>
		<groupId>com.spi</groupId>
		<artifactId>hello-world-api</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</dependency>
</dependencies>
  • 实现类
package com.spi.impl;

import com.spi.api.HelloService;

public class HelloServiceProvider implements HelloService{

	public void sayHello() {
		System.out.println("Hello World.");
	}

}
  • 配置

服务为了被发现,需要在META-INF/services/目录下创建com.spi.api.HelloService文件,内容为:

com.spi.impl.HelloServiceProvider

3、应用程序

  • 工程

hello-world-app:

<groupId>com.spi</groupId>
<artifactId>hello-world-app</artifactId>
<version>0.0.1-SNAPSHOT</version>

<dependencies>
	<dependency>
		<groupId>com.spi</groupId>
		<artifactId>hello-world-api</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</dependency>
	<dependency>
		<groupId>com.spi</groupId>
		<artifactId>hello-world-impl</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</dependency>
</dependencies>
  • 测试类
package com.spi.app;

import java.util.Iterator;
import java.util.ServiceLoader;

import com.spi.api.HelloService;

public class App {
	public static void main(String[] args) {
		ServiceLoader<HelloService> loader = ServiceLoader.load(HelloService.class);
		Iterator<HelloService> iterator = loader.iterator();
		while(iterator.hasNext()){
			HelloService provider = iterator.next();
			System.out.println("Provider: " + provider.getClass());
			provider.sayHello();
		}
	}
}
  • 运行结果
Provider: class com.spi.impl.HelloServiceProvider
Hello World.
参考资料

Java Service Provider Interface

Java – Service Provider Interface(SPI)