Почему я должен использовать OSGi Services для экспортированных пакетов?

Я пытаюсь разобраться с OSGi Services. Главный вопрос, который я задаю себе, заключается в следующем: какая польза от использования сервисов вместо работы с пакетами и их экспортированными пакетами?

Насколько я знаю, похоже, что концепция Late Binding имеет какое-то отношение к ней. Зависимости привязки соединены вместе при запуске пучка, поэтому они довольно исправлены, я думаю. Но с услугами, похоже, почти то же самое. Пакет запускает и регистрирует службы или привязки к службам. Конечно, услуги могут приходить и уходить, когда они хотят, и вам нужно следить за этими шансами. Но основная идея не кажется мне совсем другой.

Другим аспектом этого является то, что услуги более гибкие. Для одного конкретного интерфейса может быть много реализаций. С другой стороны, может быть множество различных реализаций для определенного экспортированного пакета.

В другом тексте я читал, что недостатком использования экспортированных пакетов является то, что они делают приложение более хрупким, чем сервисы. Автор писал, что если вы удаляете один пакет из графика зависимости, то другие зависимости больше не будут выполняться, что может вызвать эффект домино на всем графике. Но не может ли такое же случиться, если служба отключится? Для меня это похоже на то, что сервисные зависимости не лучше, чем зависимости пакетов.

До сих пор я не мог найти сообщение в блоге, книгу или презентацию, в которых можно было бы четко описать, почему услуги лучше, чем просто раскрывать функциональность, экспортируя и импортируя пакеты.

Подводя итоги:

Каковы основные преимущества использования служб OSGi, которые делают их выше, чем экспорт и импорт пакетов?


Добавление

Я попытался собрать дополнительную информацию об этой проблеме и придумал какое-то сравнение между простым экспортом/импортом пакетов и сервисов. Возможно, это поможет нам найти удовлетворительный ответ.

  • Start/Stop/Update

    Оба, пакеты (следовательно, пакеты) и сервисы могут быть запущены и остановлены. Кроме того, они могут быть обновлены. Услуги также привязаны к самому жизненному циклу пучка. Но в этом случае я имею в виду, если вы можете запускать и останавливать службы или пакеты (чтобы экспортированные пакеты "исчезали" ).

  • Отслеживание изменений

    ServiceTracker и BundleTracker позволяют отслеживать и реагировать на изменения в доступности пакетов и сервисов.

  • Конкретные зависимости от других пакетов или сервисов.

    Если вы хотите использовать экспортированный пакет, вам необходимо его импортировать.

    Import-Package: net.jens.helloworld
    

    Будет ли net.jens.helloworld предоставлять услугу, мне также потребуется импортировать пакет, чтобы получить интерфейс.

    Таким образом, в обоих случаях их будет какая-то "плотная связь" с более или менее конкретным пакетом.

  • Возможность иметь более одной реализации

    Конкретные пакеты могут экспортироваться более чем одним пакетом. Может быть пакет net.jens.twitterclient, который экспортируется пакетом A и пакетом B. То же самое относится к службам. Интерфейс net.jens.twitterclient.TwitterService может быть опубликован пучками A и B.

Чтобы суммировать это здесь, короткое сравнение (Exported packages/services):

  • ДА/ДА
  • ДА/ДА
  • ДА/ДА
  • ДА/ДА

Поэтому нет никакой разницы.

Кроме того, кажется, что услуги добавляют дополнительную сложность и вводят еще один уровень зависимостей (см. image ниже).

alt text http://img688.imageshack.us/img688/4421/bundleservicecomparison.png

Итак, если нет никакой реальной разницы между экспортируемыми пакетами и услугами, в чем преимущество использования сервисов?

Мое объяснение:

Использование служб кажется более сложным. Но сами услуги кажутся более легкими. Это должно быть различие (с точки зрения производительности и ресурсов), если вы запускаете/останавливаете весь пакет или просто начинаете и останавливаете конкретную услугу.

С архитектурной точки зрения я также предполагаю, что связки можно рассматривать как основу приложения. Фонд не должен часто меняться с точки зрения запуска и остановки пучков. Функциональность обеспечивается службами этих пакетов в некотором динамическом слое над слоем пакета. Этот "сервисный уровень" может подвергаться частым изменениям. Например, служба для запроса базы данных не регистрируется, если база данных отключена.


Каково ваше мнение? Я начинаю получать весь смысл услуг, или я все еще думаю не так? Есть ли вещи, которые мне не хватает, что сделает услуги гораздо более привлекательными по сравнению с экспортируемыми пакетами?

Ответ 1

Его довольно просто: Связки просто предоставляют классы, которые вы можете использовать. Используя импорт/экспорт, вы можете защитить видимость и избежать (например) конфликтов версий. Службы - это экземпляры классов, которые удовлетворяют определенному контракту (интерфейсам).

Таким образом, при использовании Сервисов вам не нужно заботиться о происхождении реализации или о деталях реализации. Они могут даже измениться, пока вы используете определенную услугу.

Когда вы просто хотите полагаться на Bundle Layer OSGi, вы легко вводите перекрестные зависимости к конкретным реализациям, которых вы обычно никогда не хотите. (читайте ниже о DI)

Это не только OSGi - просто хорошая практика.

В мирах без OSGi вы можете использовать фреймворки зависимостей (DI), такие как Guice, Spring или аналогичные. OSGi имеет уровень сервиса, встроенный в фреймворк, и позволяет использовать более высокий уровень фреймворков (Spring, Guice). - поэтому в конце вы обычно не используете API OSGi Service API напрямую, но адаптеры DI от дружественных к пользователю фреймворков (Spring → Spring DM, Guice → Peaberry и т.д.).

НТН, Toni

Ответ 2

Я бы рекомендовал приобрести эту книгу. Это отличная работа, объясняющая услуги и ходьба через создание нетривиального приложения, которое использует OSGi Services.

http://equinoxosgi.org/

Моя компания регулярно создает приложения с более 100 приложениями, использующими сервисы. Основными преимуществами, которые мы получаем от использования сервисов, являются:

1) Свободное соединение реализации производителя/потребителя

2) Поставщики услуг с горячей заменой

3) Архитектура чистого приложения

Ответ 3

Когда вы начинаете работу с OSGi, всегда легче начать с подхода экспорт-пакет, он, безусловно, чувствует себя более похожим на Java. Но когда ваше приложение начинает расти, и вам нужна небольшая динамичность, услуги - это путь.

Экспорт-пакет выполняет только разрешение при запуске, тогда как службы - это постоянное разрешение (которое вы можете захотеть или нет). С точки зрения поддержки услуги могут быть очень страшными (является детерминированным? Как я могу реплицировать проблемы?), Но он также очень эффективен.

Питер Кринс объясняет, почему он думает, что Сервисы - это изменение парадигмы так же, как и в свое время. см. μServices и Канальная лента.

Во всем моем опыте OSGi у меня еще не было случая реализовать сложные сервисы (т.е. более одного уровня), и, безусловно, аннотации кажутся подходящими. Вы также можете использовать Spring динамический модуль, чтобы облегчить боль при работе с треерами обслуживания. (и многие другие варианты, такие как iPOJO и Blueprint)

Ответ 5

Давайте рассмотрим два следующих сценария:

  • Пакет A предлагает услугу, которая является арифметическим добавлением add(x,y) return x+y. Для этого он экспортирует "пакет mathOpe" с "интерфейсом IAddition" и регистрирует службу в реестре служб. Связи B, C, D,... используют эту услугу.

  • Bundle A экспортирует "пакет mathOpe", где мы нашли класс "Дополнение", раскрывающий операцию (x+y)<--add(x,y). Связки B, C, D,... импортируют пакет mathOpe.

Сравнение сценария 1 и сценария 2:

  • Только один экземпляр реализации против многих экземпляров (не стесняйтесь сделать его статическим!)
  • Динамическое управление сервисами, запуск, остановка, обновление и отсутствие управления, потребитель владеет реализацией ( "услуга" ).
  • Гибкий (мы можем представить удаленный сервис по сети), а не гибкий

... среди прочих.

PS: Я не эксперт OSGI и не Java, этот ответ показывает только мое понимание явлений:)

Ответ 6

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

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

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