java spi_Java SPI(服务提供商接口)和ServiceLoader

Java SPI(服务提供者接口)是一种动态加载服务的机制。包括四部分:服务提供者接口、服务提供者实现类、服务提供者配置文件和服务加载器。ServiceLoader是主要类,用于加载服务提供者接口的服务。文章通过示例解释了如何创建SPI接口,实现类,配置文件以及如何使用ServiceLoader加载服务。
摘要由CSDN通过智能技术生成

java spi

Java SPI (Service Provider Interface) is the mechanism to load services dynamically. We can implement Java SPI in our application by following the specific set of rules and load the services using the ServiceLoader class.

Java SPI(服务提供者接口)是动态加载服务的机制。 通过遵循特定的规则集,我们可以在我们的应用程序中实现Java SPI,并使用ServiceLoader类加载服务。



Java SPI组件 (Java SPI Components)

There are four components in the SPI implementation.

SPI实现中包含四个组件。

  1. Service Provider Interface: An interface or abstract class that defines the contract for the service provider implementation classes.

    服务提供者接口 :定义服务提供者实现类的协定的接口抽象类。
  2. Service Providers: The implementation classes that actually provides the services.

    服务提供者 :实际提供服务的实现类。
  3. SPI Configuration File: A special file that provides the logic to look for the services implementations. The file name must be present in the META-INF/services directory. The file name should be exactly same as the service provider interface fully qualified name. Every line in the file have one implementation service class details, again the fully qualified name of the service provider class.

    SPI配置文件 :一个特殊的文件,提供查找服务实现的逻辑。 文件名必须存在于META-INF / services目录中。 文件名应与服务提供商接口标准名称完全相同。 文件中的每一行都有一个实现服务类详细信息,再次是服务提供者类的完全限定名称。
  4. ServiceLoader: The Java SPI main class that is used to load the services for a service provider interface. There are various utility methods in the ServiceLoader to get specific implementations, iterate through them, or reload the services again.

    ServiceLoader :Java SPI主类,用于为服务提供者接口加载服务。 ServiceLoader中有多种实用程序方法可用于获取特定的实现,对其进行迭代或重新加载服务。


Java服务提供者接口示例 (Java Service Provider Interfaces Examples)

The java.util.spi package provides a lot of service provider interfaces that can be implemented to provide services.

java.util.spi包提供了许多服务提供程序接口,可以将其实现以提供服务。

  1. ResourceBundleProvider, ResourceBundleControlProvider, and AbstractResourceBundleProvider: Service Provider interfaces and abstract class for Resource Bundle implementation classes.

    ResourceBundleProvider,ResourceBundleControlProvider和AbstractResourceBundleProvider:资源提供程序实现类的服务提供程序接口和抽象类。
  2. LocaleServiceProvider, CalendarDataProvider, CalendarNameProvider, CurrencyNameProvider, TimeZoneNameProvider, and LocaleNameProvider: for implementing Locale specific service providers.

    LocaleServiceProvider,CalendarDataProvider,CalendarNameProvider,CurrencyNameProvider,TimeZoneNameProvider和LocaleNameProvider:用于实现特定于区域设置的服务提供者。
Java SPI Interfaces List

Java SPI Interfaces List

Java SPI接口列表



Java SPI示例 (Java SPI Example)

Let’s create an implementation of SPI and load some services using the ServiceLoader class.

让我们创建SPI的实现,并使用ServiceLoader类加载一些服务。



1.服务提供商接口 (1. Service Provider Interface)

Let’s say we have a MessageServiceProvider interface that defines the contract for the service provider implementations.

假设我们有一个MessageServiceProvider接口,它定义了服务提供者实现的合同。

package com.journaldev.serviceproviders;

public interface MessageServiceProvider {

	void sendMessage(String message);
}


2.服务提供商实施类 (2. Service Provider Implementation Classes)

We want to support email messages and push notification messages. So we will create two service provider implementations of MessageServiceProvider interface – EmailServiceProvider and PushNotificationServiceProvider.

我们希望支持电子邮件和推送通知消息。 因此,我们将创建MessageServiceProvider接口的两个服务提供程序实现-EmailServiceProvider和PushNotificationServiceProvider。

package com.journaldev.serviceproviders;

public class EmailServiceProvider implements MessageServiceProvider {

	public void sendMessage(String message) {
		System.out.println("Sending Email with Message = "+message);
	}

}
package com.journaldev.serviceproviders;

public class PushNotificationServiceProvider implements MessageServiceProvider {

	public void sendMessage(String message) {
		System.out.println("Sending Push Notification with Message = "+message);
	}

}


3.服务提供商配置文件 (3. Service Provider Configuration File)

The configuration file has to be created in the META-INF/services directory. Its name should be “com.journaldev.serviceproviders.MessageServiceProvider“. We will specify both the implementation classes in this file.

必须在META-INF / services目录中创建配置文件。 其名称应为“ com.journaldev.serviceproviders.MessageServiceProvider ”。 我们将在此文件中指定两个实现类。

com.journaldev.serviceproviders.EmailServiceProvider
com.journaldev.serviceproviders.PushNotificationServiceProvider


4.加载服务的ServiceLoader示例 (4. ServiceLoader Example to Load Services)

Finally, we have to load the services using the ServiceLoader class. Here is a simple test program showing its usage.

最后,我们必须使用ServiceLoader类加载服务。 这是一个显示其用法的简单测试程序。

package com.journaldev.test;

import java.util.Optional;
import java.util.ServiceLoader;

import com.journaldev.serviceproviders.MessageServiceProvider;

public class ServiceLoaderTest {

	public static void main(String[] args) {
		ServiceLoader<MessageServiceProvider> serviceLoader = ServiceLoader.load(MessageServiceProvider.class);

		for (MessageServiceProvider service : serviceLoader) {
			service.sendMessage("Hello");
		}

		// using Java 8 Optional to get the first service
		Optional<MessageServiceProvider> firstService = serviceLoader.findFirst();
		if (firstService.isPresent()) {
			firstService.get().sendMessage("Hello Friend");
		}

		// using Java 8 forEach() method
		serviceLoader.forEach((service) -> service.sendMessage("Have a Nice Day!"));

		// Total Number of Loaded Services
		System.out.println(serviceLoader.stream().count());

	}

}

When we run the above program, we get the following output.

当我们运行上面的程序时,我们得到以下输出。

Sending Email with Message = Hello
Sending Push Notification with Message = Hello
Sending Email with Message = Hello Friend
Sending Email with Message = Have a Nice Day!
Sending Push Notification with Message = Have a Nice Day!
2

The below image shows our final project structure and SPI components.

下图显示了我们的最终项目结构和SPI组件。

Java SPI Example Project Structure

Java SPI Example Project Structure

Java SPI示例项目结构



ServiceLoader重要方法 (ServiceLoader Important Methods)

Let’s look at the important methods of the ServiceLoader class.

让我们看一下ServiceLoader类的重要方法。

  • load(): The static method to load the services of a particular SPI.

    load():加载特定SPI服务的静态方法。
  • findFirst(): returns the first service available for this service provider.

    findFirst():返回可用于该服务提供者的第一个服务。
  • forEach(): useful to run some code for every service provider in this service loader instance.

    forEach() :在此服务加载器实例中为每个服务提供者运行一些代码很有用。
  • stream(): returns the stream of the service providers in this service loader.

    stream() :返回此服务加载器中服务提供者的流。
  • iterator(): returns an iterator of the service providers.

    iterator():返回服务提供者的迭代器
  • reload(): reloads the service providers. It’s useful when we change the service provider configurations on the fly and want to reload the services list.

    reload():重新加载服务提供商。 当我们即时更改服务提供商的配置并希望重新加载服务列表时,这很有用。


结论 (Conclusion)

Java SPI provides an easy way to dynamically configure and load the services in our application. However, it depends a lot on the service configuration file and any change in the file can break the application.

Java SPI提供了一种简单的方法来动态配置和加载应用程序中的服务。 但是,这在很大程度上取决于服务配置文件,并且文件中的任何更改都可能破坏应用程序。



参考资料 (References)



GitHub Repository. GitHub存储库中检出完整的项目。

翻译自: https://www.journaldev.com/31602/java-spi-service-provider-interface-and-serviceloader

java spi

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值