1. Java 9中的服务提供者接口
Java 9 引入了一种新的机制——模块化,它引进了服务提供者接口 (Service Provider Interface, SPI) 概念,允许第三方插件为其他模块提供抽象实现。
在 Java 9 之前,服务提供者接口是通过在类路径中搜索实现类来工作的。Java 9 使用模块路径替代了类路径,因此服务提供者接口的查找和使用发生了相应的变化。
2. 服务提供者接口的定义
服务提供者接口本身不提供任何实现。相反,它通常定义了一些方法,供第三方插件实现并将其注册为服务,允许服务消费者查找和使用服务实现。
服务提供者接口定义必须遵循以下规则:
接口必须是 public 的,并与服务类置于同一包中
接口名称必须以 ServiceProvider 命名
public interface MyService {
void doSomething();
}
public interface MyServiceProvider {
MyService createService();
}
3. 服务实现
服务实现通常是第三方插件,它们实现了服务提供者接口并将其注册到系统中。
服务实现必须遵循以下规则:
服务实现必须是 public 的,并与服务提供者接口在同一包中
服务实现必须包含一个 public 无参构造函数
在 jar 文件的 META-INF/services 目录中,创建一个文件并命名该文件与服务提供者接口相同的全限定名,例如:com.example.MyServiceProvider
文件的内容应为服务实现的全限定名,例如:com.example.MyServiceProviderImpl
可以在同一个文件中列出多个服务实现类,每行一个
下面是一个服务提供者接口的示例:
public interface MyService {
void doSomething();
}
public interface MyServiceProvider {
MyService createService();
}
public class MyServiceImpl1 implements MyService {
public void doSomething() {
// ...
}
}
public class MyServiceImpl2 implements MyService {
public void doSomething() {
// ...
}
}
在 jar 文件的 META-INF/services 目录中,应创建一个名为 "com.example.MyServiceProvider" 的文件,并在其中列出服务提供者类:
com.example.MyServiceImpl1
com.example.MyServiceImpl2
4. 服务消费者的使用
服务消费者使用 ServiceLoader
类在运行时查找并使用已注册的服务实现。在使用服务之前,应先通过指定服务提供者接口来加载服务对象。
以下是一个使用服务的示例:
ServiceLoader<MyServiceProvider> loader = ServiceLoader.load(MyServiceProvider.class);
for (MyServiceProvider provider : loader) {
MyService myService = provider.createService();
myService.doSomething();
}
ServiceLoader 实例是延迟初始化的,它将在首次迭代时加载服务提供者。你可以通过 reload()
方法重新加载服务提供者,或通过 iterator()
方法获得迭代器。
5. 结论
服务提供者接口 (SPI) 是 Java 9 中的一个重要功能,它允许第三方插件注册和实现抽象接口。通过使用 ServiceLoader
类在运行时查找服务类,可以轻松地使用已注册的服务实现。
有关服务提供者接口和其他 Java 9 功能的更多信息,请参阅官方文档。