Подтвердить что ты не робот

Инъекция зависимостей в средах OSGI

Сначала немного фона:

Я работаю над некоторым прототипом кода webapp, основанным на Apache Sling, который основан на OSGI и работает на Apache Felix. Я по-прежнему относительно новичок в OSGI, хотя я думаю, что уже понял большинство концепций. Однако, что меня озадачивает, так это то, что я не смог найти "полную" схему внедрения зависимостей (DI). Я успешно использовал рудиментарный DI, используя Declarative Services (DS). Но я понимаю, что DS используется для ссылки - как я могу это поставить? - OSGI зарегистрировал сервисы и компоненты вместе. И для этого он отлично работает, но я лично использую рамки DI, такие как Guice, чтобы объединить все графические объекты и поместить объекты в правильные области (подумайте @RequestScoped или @SessionScoped например). Однако ни одна из конкретных структур OSGI, на которые я смотрел, похоже, поддерживает эту концепцию.

Я начал читать о чертежах OSGI и iPOJO, но эти рамки, похоже, больше связанные с подключением служб OSGI, а не с предоставлением полного решения DI. Я должен признать, что я еще не сделал никаких образцов, поэтому мое впечатление может быть неправильным.

Являясь расширением для Guice, я экспериментировал с Peaberry, однако мне очень трудно найти документацию, и, хотя я получил базовую работу DI, много функциональных возможностей guice-servlet (автоматический ввод в фильтры, сервлеты и т.д.) вообще не работало.

Итак, мои вопросы таковы:

  • Как декларативные службы сравниваются с "традиционными" DI, такими как Guice или Spring? Решают ли они одну и ту же проблему или они направлены на различные проблемы?
  • Все решения OSGI, которые я видел до сих пор, не имеют концепции областей для DI. Например, Guice + guice-servlet имеет зависящие от запросов зависимости, которые делают записи веб-приложений действительно чистыми и легкими. Я просто пропустил это в документах или эти проблемы не охвачены ни одной из этих фреймворков?
  • Являются JSR 330 и OSGI основаны на DI двух разных мирах? iPOJO, например, приносит свои собственные аннотации и Felix SCR Annotations, кажется, совсем другой мир.
  • Есть ли у кого-нибудь опыт создания OSGI-систем и DI? Может быть, даже пример кода на github?
  • Кто-нибудь использует разные технологии, такие как Guice и iPOJO, или это просто сумасшедшая идея?

Извините за довольно длинный вопрос.

Любая обратная связь очень приветствуется.


Обновление

Инъекция с областью: инъекция с областью - это полезный механизм, позволяющий автоматически вводить объекты из определенного жизненного цикла. Подумайте, например, некоторые из вашего кода полагаются на объект сеанса Hibernate, который создается как часть фильтра сервлета. Пометив зависимость, контейнер автоматически перестроит граф объекта. Может быть, есть только разные подходы к этому?

JSR 330 против DS: из всех ваших превосходных ответов я вижу, что это две разные вещи. Это ставит вопрос, как обращаться с сторонними библиотеками и фреймворками, использующими аннотации JSR 330 при использовании в контексте OSGI? Какой хороший подход? Запуск контейнера JSR 330 в Bundle?

Я ценю все ваши ответы, вы были очень полезны!

4b9b3361

Ответ 1

Общий подход

Самый простой способ иметь инъекцию зависимостей с Apache Sling и используемую в кодовой базе - использовать maven-scr-plugin.

Вы можете аннотировать свои классы java, а затем во время сборки вызывать плагин SCR, либо как плагин Maven, либо как задачу Ant.

Например, чтобы зарегистрировать сервлет, вы можете сделать следующее:

@Component // signal that it OSGI-managed
@Service(Servlet.class) // register as a Servlet service
public class SampleServlet implements Servlet {   
   @Reference SlingRepository repository; // get a reference to the repository    
}

Конкретные ответы

Как декларативные службы сравниваются с "традиционными" DI, такими как Guice или Spring? Решают ли они ту же проблему или же они ориентированы на разные проблемы?

Они решают одну и ту же проблему - инъекцию зависимости. Однако (см. Ниже) они также построены с учетом динамических систем, в которых услуги могут появляться или исчезать в любое время.

Все решения OSGI, которые я видел до сих пор, не имеют концепции областей для DI. Например, Guice + guice-servlet имеет зависящие от запросов зависимости, которые делают записи веб-приложений действительно чистыми и легкими. Я просто пропустил это в документах или эти проблемы не охвачены ни одной из этих фреймворков?

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

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

Хорошим примером является сеанс JCR. Он автоматически создается с правильными привилегиями, и на практике это DAO с областью запросов. То же самое относится к ресурсу Rlingolver Sling.

Если вам нужно работать с одним пользователем, самый простой подход - иметь службы, которые получают JCR Session или Sling ResourceResolver, и использовать их для выполнения нужной вам работы. Результаты будут автоматически скорректированы для привилегий текущего пользователя без каких-либо дополнительных усилий.

Являются ли JSR 330 и OSGI на основе DI двух разных миров? iPOJO, например, приносит свои собственные аннотации, и Felix SCR Annotations кажется совершенно другим миром.

Да, они разные. Вы должны иметь в виду, что хотя Spring и Guice более популярны, службы OSGi более сложны и поддерживают больше случаев использования. В пакетах OSGi (и неявно сервисы) бесплатно приходят и уходят в любое время.

Это означает, что когда у вас есть компонент, который зависит от службы, которая только что стала недоступной, ваш компонент деактивирован. Или, когда вы получаете список компонентов (например, реализации сервлетов) и один из них деактивирован, вы об этом уведомлены. Насколько мне известно, ни Spring, ни Guice не поддерживают это, поскольку их проводки статичны.

Это большая гибкость, которую предоставляет OSGi.

Есть ли у кого-нибудь опыт создания OSGI-систем и DI? Может быть, даже пример кода на github?

Там содержится большое количество выборок в Sling Samples SVN repository. Вы должны найти большую часть того, что вам нужно.

Кто-нибудь использует разные технологии, такие как Guice и iPOJO, или это просто сумасшедшая идея?

Если у вас есть фреймворки, которые настроены с аннотациями JSR 330, имеет смысл настроить их во время выполнения с помощью Guice или Spring или что-то для вас работает. Однако, как отметил Нил Бартлетт, это не будет работать с перекрестными связями.

Ответ 2

Я просто хотел бы добавить немного больше информации для Роберта, в частности, в отношении JSR330 и DS.

Декларативные службы, Blueprint, iPOJO и другие "компонентные модели OSGi" преимущественно, предназначенные для инъекции служб OSGi. Они немного сложнее в обращении, чем обычные зависимости, потому что они могут приходить и уходить в любое время, в том числе в ответ на внешние события (например, отключенные сети) или действия пользователя (например, удаленный пакет). Поэтому все эти компонентные модели обеспечивают дополнительный слой жизненного цикла поверх прозрачных фреймворков зависимостей.

Это основная причина, почему аннотации DS отличаются от JSR330... JSR330 не обеспечивают достаточной семантики для решения жизненного цикла. Например, они ничего не говорят о:

  • Когда следует вводить зависимость?
  • Что нам делать, когда зависимость недоступна (т.е. является ли она необязательной или обязательной)?
  • Что нам делать, если служба, которую мы используем, уходит?
  • Можем ли мы динамически переключаться с одного экземпляра службы на другой?
  • и т.д...

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

Не должно возникнуть проблемы с использованием существующей рамки DI для подключения зависимостей внутри пакета. Например, у меня был клиент, который использовал Guice для подключения внутренних частей некоторых компонентов Declarative Services. Однако я склонен подвергать сомнению ценность этого, потому что, если вам нужно DI внутри вашего пакета, это говорит о том, что ваш пакет может быть слишком большим и бессвязным.

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

Ответ 3

У меня есть некоторый опыт в создании приложений с использованием Aries Blueprint. Он имеет некоторые очень приятные функции в отношении сервисов OSGi и поддержки администраторов config.

Если вы ищете несколько замечательных примеров, посмотрите код Apache Karaf, который использует план для всей своей проводки. См. http://svn.apache.org/repos/asf/karaf/

У меня также есть некоторые tutortials для Blueprint и Apache Karaf на моем сайте: http://www.liquid-reality.de/display/liquid/Karaf+Tutorials

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

Ответ 4

Я использую osgi и DI для текущего моего проекта, я выбрал gemini blueprint, потому что это вторая версия SPRING ДИНАМИЧЕСКИЕ МОДУЛИ, Основываясь на этой информации, я предлагаю вам прочитать SPRING Динамические модули в действии. Эта книга поможет вам понять некоторые детали и указать, как строить архитектуру и почему это хорошо:)

Ответ 5

Я могу порекомендовать Bnd, и если вы также используете Eclipse IDE отдельно Bndtools. С этим вы можете избежать описания DS в XML и вместо этого использовать аннотации. Для DI существует специальная аннотация Reference. У этого есть также фильтр, где вы можете ссылаться только на специальное подмножество служб.

Ответ 6

Включение в подобную проблему архитектуры здесь - как сказал Роберт в своем ответе:

Если вы нуждаетесь в работе с пользователем, самый простой способ - имеют службы, которые получают сессию JCR или Sling ResourceResolver и использовать их для выполнения необходимой вам работы. Результаты будут автоматически настраивается для привилегий текущего пользователя без любые дополнительные усилия.

Экстраполируя это (и то, что я в настоящее время кодирую), одним из подходов было бы добавить @param resourceResolver к любым методам @Service, чтобы вы могли передать объект с соответствующим объектом запроса, который будет использоваться по цепочке выполнения.

В частности, у нас есть слой XXXXService/XXXXDao, называемый из XXXXServlet/XXXXViewHelper/JSP эквивалентов. Поэтому, управляя всеми этими компонентами с помощью аннотаций OSGI @Service, мы можем легко подключить весь стек.

Недостатком здесь является то, что вам нужно заманить дизайн интерфейса с помощью параметров ResourceResolver или Sessions.

Сначала мы попытались ввести ResourceResolverFactory в слой DAO, чтобы мы могли легко получить доступ к сеансу по желанию через factory. Однако мы взаимодействуем с сеансом в нескольких точках иерархии и несколько раз за запрос. Это привело к закрытым закрытым исключениям.

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

С помощью инъекции с областью запросов на уровнях обслуживания вы можете просто передать ResourceResolver в качестве аргумента конструктора и вместо этого использовать переменную экземпляра. Конечно, недостатком здесь является то, что вам нужно будет подумать о коде запроса-scope vs. prototype-scope и соответствующим образом разделить.

Кажется, что это была бы общая проблема, когда вы хотите выделить проблемы в код службы/дао, оставив JCR-взаимодействия в DAO, аналогичные Hibernate, как вы можете легко получить по запросу Session до выполнять операции репо?