Java SPI简介
一、概述
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.Driver
、java.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.