Service Provider Interface (SPI) в Java SE| OTUS

Курсы

Программирование
iOS Developer. Basic
-23%
Python Developer. Professional
-13%
Golang Developer. Professional
-17%
Python Developer. Basic
-16%
iOS Developer. Professional
-13%
C# ASP.NET Core разработчик
-18%
Unity Game Developer. Professional
-11%
React.js Developer
-12%
Android Developer. Professional
-7%
Software Architect
-12%
C++ Developer. Professional
-8%
Разработчик C#
-8%
Backend-разработчик на PHP
-8%
Архитектура и шаблоны проектирования
-12%
Программист С Разработчик на Spring Framework MS SQL Server Developer AWS для разработчиков Cloud Solution Architecture Разработчик голосовых ассистентов и чат-ботов Vue.js разработчик VOIP инженер Нереляционные базы данных Супер - интенсив по паттернам проектирования Супер-практикум по использованию и настройке GIT IoT-разработчик Advanced Fullstack JavaScript developer Супер-интенсив Azure
Инфраструктура
Мониторинг и логирование: Zabbix, Prometheus, ELK
-17%
DevOps практики и инструменты
-18%
Архитектор сетей
-21%
Инфраструктурная платформа на основе Kubernetes
-22%
Супер-интенсив «IaC Ansible»
-16%
Супер-интенсив по управлению миграциями (DBVC)
-16%
Administrator Linux. Professional
-5%
Administrator Linux.Basic
-10%
Супер-интенсив «ELK»
-10%
Базы данных Сетевой инженер AWS для разработчиков Cloud Solution Architecture Разработчик голосовых ассистентов и чат-ботов Внедрение и работа в DevSecOps Супер-практикум по работе с протоколом BGP Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Супер-интенсив «СУБД в высоконагруженных системах»
Специализации Курсы в разработке Подготовительные курсы
+7 499 938-92-02

Service Provider Interface (SPI)

VKjavaDeep1.png

Вот представьте: повысили вас до ведущего разработчика! Не номинально, а по-настоящему – будете отвечать за техническое развитие продукта. И вот заходите вы в почту, естественно, чтобы должность в подписи поменять, а там...

Вместе с полномочиями пришла и ответственность: – пользователи не хотят больше устанавливать дистрибутив приложения целиком, они хотят устанавливать только то, что планируют использовать; – техническая поддержка просит реализовать наконец возможность автоматического обновления приложения; – разработчики тоже ругают долгий цикл доставки обновлений пользователям; – отдел продаж требует технически поддержать новую модель гибкого ценообразования - теперь пользователь покупает только нужный ему функционал; – партнёры хотят создавать собственные расширения к продукту; – юристы перестраховываются и требуют убрать из состава дистрибутива коммерческого продукта ту часть функционала, которая использует некоторые open source библиотеки, чтобы избежать необходимости публикации исходников...

Как разрубить этот «гордиев узел»?

Разделить монолитное приложение на модули! Модули могут загружаться по требованию и обновляться при необходимости в процессе работы основного приложения.

А как это сделать? Выбор велик. Можно просидеть все выходные, изобретая собственный «велосипед». Можно вооружиться кофе-машиной и погрузиться в изучение вселенной OSGi...

А можно вспомнить, чему учат на курсе OTUS: в состав Java SE входит технология Service Provider Interface (SPI).

О ней и пойдёт речь далее

Технология SPI позволяет разделить сервисы (бизнес-логику) приложения на интерфейс и его реализации. Таким образом, реализация сервиса может распространяться в виде отдельного jar-архива и включаться в работу уже в процессе работы основного приложения.

Эта технология, например, применяется в хорошо известной вам JDBC для загрузки драйвера конкретной СУБД.

На практике это выглядит так:

1) Создаёте общий интерфейс для группы ваших модулей Сигнатуры методов интерфейса могут быть абсолютно любыми. Например:

public interface Plugin { 
        Object execute(Object input); 
}

2) Создаёте необходимое количество классов-реализаций ваших модулей Например:

public class EchoPlugin implements Plugin { 
  public Object execute(Object input) { 
        // Делаем что-то полезное 
        return input; 
  } 
} 

3) Определяете стратегию упаковки классов-реализаций в jar-архивы В один jar-архив может быть упакован один или несколько классов-реализаций. Как правило, один архив содержит реализацию одного логически целостного модуля приложения. Внутри каждого jar-архива в каталоге \META-INF\services должен находится текстовый файл в кодировке UTF-8, название которого совпадает с полным именем интерфейса, созданного в п.1, например, ru.otus.Plugin. В тексте файла должны быть указаны полные имена классов-реализаций, содержащихся в jar-архиве, например:

ru.otus.EchoPlugin 
ru.otus.CopyPlugin 

4) В программном коде основного приложения создаёте ClassLoader для загрузки классов-реализаций из jar-архива

URL[] moduleUrls = new URL[]{new URL("http://example.com/module-1.0.jar")};
URLClassLoader urlClassLoader = new URLClassLoader(moduleUrls);

5) А затем, получаете и используете реализации необходимых вам модулей

for (final Plugin plugin : ServiceLoader.load(Plugin.class, urlClassLoader)) { 
        Object result = plugin.execute(new Object()); 
} 

Всё, пользуйтесь!

Есть вопрос? Напишите в комментариях!

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться