Рубрики
Без рубрики

Java SPI (Интерфейс поставщика услуг) и загрузчик служб

Java SPI (Интерфейс поставщика услуг) – это механизм динамической загрузки служб. Мы можем реализовать Java API в нашем приложении, следуя

Автор оригинала: Pankaj Kumar.

Java SPI (Интерфейс поставщика услуг) – это механизм динамической загрузки служб. Мы можем реализовать Java API в нашем приложении, следуя определенному набору правил, и загрузить службы с помощью класса ServiceLoader.

Компоненты Java API

В реализации SPI есть четыре компонента.

  1. Интерфейс поставщика услуг : интерфейс или абстрактный класс , определяющий контракт для классов реализации поставщика услуг.
  2. Поставщики услуг : Классы реализации, которые фактически предоставляют услуги.
  3. Файл конфигурации SPI : Специальный файл, предоставляющий логику для поиска реализаций служб. Имя файла должно присутствовать в каталоге META-INF/services . Имя файла должно быть точно таким же, как полное имя интерфейса поставщика услуг. Каждая строка в файле содержит сведения об одном классе службы реализации, опять же полное имя класса поставщика услуг.
  4. ServiceLoader : Основной класс Java SPI, используемый для загрузки служб для интерфейса поставщика услуг. В загрузчике служб существуют различные служебные методы для получения конкретных реализаций, их перебора или повторной загрузки служб.

Примеры интерфейсов поставщиков услуг Java

Пакет java.util.spi предоставляет множество интерфейсов поставщиков услуг, которые могут быть реализованы для предоставления услуг.

  1. ResourceBundleProvider, ResourceBundleControlProvider и абстрактный ResourceBundleProvider: интерфейсы поставщика услуг и абстрактный класс для классов реализации пакета ресурсов.
  2. LocaleServiceProvider, CalendarDataProvider, CalendarNameProvider, CurrencyNameProvider, TimeZoneNameProvider и LocaleNameProvider: для реализации поставщиков услуг, специфичных для конкретного региона.

Пример Java API

Давайте создадим реализацию SPI и загрузим некоторые службы с помощью класса ServiceLoader.

1. Интерфейс Поставщика Услуг

Допустим, у нас есть Поставщик услуг сообщений интерфейс, который определяет контракт для реализаций поставщика услуг.

package com.journaldev.serviceproviders;

public interface MessageServiceProvider {

	void sendMessage(String message);
}

2. Классы Реализации Поставщика Услуг

Мы хотим поддерживать сообщения электронной почты и push-уведомления. Таким образом, мы создадим две реализации поставщика услуг 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. Файл Конфигурации Поставщика Услуг

Файл конфигурации должен быть создан в каталоге META-INF/services . Его имя должно быть ” com.journaldev.поставщики услуг.Поставщик услуг сообщений “. Мы укажем оба класса реализации в этом файле.

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

4. Пример загрузчика служб для загрузки служб

Наконец, мы должны загрузить службы с помощью класса 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 serviceLoader = ServiceLoader.load(MessageServiceProvider.class);

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

		// using Java 8 Optional to get the first service
		Optional 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());

	}

}

Когда мы запускаем вышеуказанную программу, мы получаем следующий результат.

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

На рисунке ниже показана наша окончательная структура проекта и компоненты SPI.

Пример структуры проекта Java API

Важные методы загрузки служб

Давайте рассмотрим важные методы класса ServiceLoader.

  • load(): Статический метод загрузки служб определенного SPI.
  • findFirst(): возвращает первую услугу, доступную для данного поставщика услуг.
  • forEach() : полезно запустить некоторый код для каждого поставщика услуг в этом экземпляре загрузчика услуг.
  • stream() : возвращает поток поставщиков услуг в этом загрузчике услуг.
  • итератор(): возвращает итератор поставщиков услуг.
  • перезагрузка(): перезагружает поставщиков услуг. Это полезно, когда мы меняем конфигурации поставщиков услуг на лету и хотим перезагрузить список услуг.

Вывод

Java API предоставляет простой способ динамической настройки и загрузки служб в нашем приложении. Однако это во многом зависит от файла конфигурации службы, и любое изменение в файле может привести к поломке приложения.

Рекомендации