Когда использовать ServiceLoader над чем-то вроде OSGi

Будучи человеком, страдающим аллергией на зависимости, когда я буду использовать что-то вроде OSGi вместо встроенного java 6 http://java.sun.com/javase/6/docs/api/java/util/ServiceLoader.html (я хочу чтобы плагины могли просто отбрасываться).

(FYI это приложение scala, открытое для любых предложений, ServiceLoader довольно чертовски близко к тому, что я хочу).

Ответ 1

Если ServiceLoader в основном соответствует вашим потребностям, это говорит о том, что вы ищете обнаружение службы через наличие файлов в пути к классу. Это лишь небольшая часть того, что предоставляет OSGi.

OSGi позволит вам динамически устанавливать пакеты, рекламировать сервисы, отзывать рекламные объявления и удалять пакеты во время работы приложения. Кроме того, как потребитель услуг, вы можете искать их с нетерпением - с фильтрацией запросов предикатов - и обнаруживать, когда предлагаемые поставщики услуг приходят и уходят. Эти связки не должны лежать на пути к классу, и они могут быть представлены в различных формах; Файлы Jar и "взорванные каталоги" - это два, которые я помню.

В отличие от этого, ServiceLoader выполняет только одно: оно предоставляет открываемые заводы. Обычно вы создаете интерфейс factory -style, который принимает некоторый аргумент, чтобы решить, может ли этот провайдер предлагать соответствующую услугу, например сопоставление заданного имени набора символов с CharsetDecoder. Там нет формализованного протокола для приобретения и освобождения услуги от такого провайдера. OSGi формализует привязку и отключение потребителей к услугам. Потребитель может получать уведомление, когда новые поставщики подключаются к сети, и поставщик может получать уведомление, когда потребитель приобретает и выпускает экземпляр службы. Если этот контроль жизненного цикла важен для вашего обслуживания, и вы отказываетесь от OSGi, вам придется самим построить это; ServiceLoader не заходит так далеко.

Вместо альтернативного поиска и использования службы вы можете использовать более пассивный, декларативный подход и позволить одному из менеджеров зависимостей OSGi соответствовать вашим заявленным потребностям доступным поставщикам услуг. Есть много менеджеров зависимостей на выбор. Spring Динамические модули является одним из самых способных.

OSGi предоставляет множество других "промежуточных программ". Я не буду пытаться продавать вас на них здесь, так как ваш вопрос фокусируется главным образом на том, чего вы бы пропустили, выбрав ServiceLoader.

Ответ 2

Как указано выше, если вас интересует простое обнаружение сервисов, то ServiceLoader - это легкий способ отделить потребителей от поставщиков. Но он не предлагает никакой помощи в создании сервисов вместе.

Например, предположим, что службе A необходимо использовать службу B. Это "зависимость от службы"... но что должно делать A, если B недоступен? В OSGi мы можем организовать, что если B не доступно, то ни один из них не будет - при условии, что зависимость является обязательной; мы также можем поддерживать дополнительные зависимости. С другой стороны, при использовании ServiceLoader служба A не имеет контроля над ее доступностью, пока JAR, заключенный в нее, находится в пути к классам... поэтому он должен обеспечивать свою функциональность даже при отсутствии требуемых услуг "back end".

Еще одна вещь, которая стоит иметь в виду с ServiceLoader, - попытаться абстрагировать механизм поиска. Механизм публикации довольно приятный, чистый и декларативный. Но поиск (через java.util.ServiceLoader) такой же уродливый, как и ад, реализованный как сканер путей к классам, который ломается ужасно, если вы помещаете код в любую среду (например, OSGi или Java EE), которая не имеет глобальной видимости. Если ваш код запутался в этом, вам будет сложно запустить его на OSGi позже. Лучше писать абстракцию, которую вы можете заменить, когда придет время.