我们如何在Java 9中创建一个服务提供者接口?

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 功能的更多信息,请参阅官方文档。

后端开发标签