OSGi: Какая разница между возможностями Import-Package/Export-Package и Require-Capability/Provide Capability?

В настоящее время я работаю со структурой OSGi, но у меня есть вопрос о некоторых концепциях, которые мне не ясны на 100%. Я сам искал его, но не смог найти достойного ответа, который бы это четко объяснял.

В связке его заголовок манифеста 2 из заголовков, которые используются, это Import-Package и Export-Package. Имена говорят сами за себя: спрос на определенный пакет и предложение определенного пакета. Чтобы получить этот пакет (или дать этот пакет), полный пакет должен быть установлен в инфраструктуре, где требуется импорт.

Но затем мы переходим к части модели Requirements-Capabilities. Это может практически сделать то же самое, что и заголовки Import-Package и Export-Package. Для этой модели Requirements-Capability есть также заголовки: Require-Capability и Provide-Capability. Опять же, это означает, что нужно что-то требовать и что-то предоставлять.

Я знаю, что модель Requirements-Capability была введена позже при разработке спецификаций OSGi. Не могу точно найти, в каком году и версии он был представлен.

Но,

  • Почему это было добавлено в спецификацию? Я не вижу, что он может предложить больше, чем то, что уже предложено в Import/Export-package: создание зависимостей от других пакетов/пакетов?

  • Может ли кто-нибудь дать мне лучшее понимание разницы (за и против) между этими двумя наборами понятий?

Ответ 1

Когда мы начинали с OSGi в 1998 году, у нас были четкие требования, но, конечно, не было четкого представления о том, что из этого выйдет. Итак, мы начали явно моделировать требования и возможности, которые у нас были: пакеты. Пакет импорта требует возможности, и эта возможность предоставляется пакетом экспорта.

В 2003 году Eclipse хотела начать использовать OSGi, но им нужно было средство, чтобы требовать другой пакет, им не понравилась идея экспорта и импорта всех своих пакетов. На самом деле, в то время они не видели преимущества пакетов. Чтобы удовлетворить их, мы добавили Require-Bundle и Fragment-Host (еще одно их желание, которое оказалось не таким хорошим).

После того, как мы указали OSGi 4.x с этими расширениями, мы начали думать о репозитории, Ричард разработал Oscar Bundle Repository. Анализируя ситуацию с новыми заголовками в OSGi 4.0, стало ясно, что реализация Import-Package во многом напоминала Require-Bundle и даже напоминала обработку Fragment-Host.

В 2006 году Ричард С. Холл и я написали RFC 112, предлагая более общую модель, которая охватила семантику существующей модели зависимостей, но не была специфичной для каждого типа требований. То есть для распознавателя Framework файлы Import-Package и Require-Bundle различаются только по пространству имен. Думая об импорте-пакете как об общем требовании и об экспорте-пакете как об общем способе, модель репозитория была предельно простой. Более того, он был расширяемым, поскольку мы всегда могли добавить больше пространств имен. Это сделало распознаватель полностью независимым от фактически используемых пространств имен.

После нескольких очень жарких дискуссий экспертная группа по OSGi Core Platform решила принять основную идею и разработала спецификации требований и возможностей. Хотя изначально это была модель для хранилища, она оказалась очень полезной для самой платформы. Поэтому мы решили адаптировать существующие спецификации к этой модели. OSGi 4.3 внутренне моделирует Import-Package, Export-Package, Require-Bundle и т.д. В качестве требований и возможностей ресурса (связки). Для обратной совместимости мы сохранили существующие заголовки, но они внутренне переведены на требования и возможности.

Тогда наконец ответим на ваш вопрос. Со временем спецификации OSGi добавили все больше и больше пространств имен. Пространство имен похоже на тип для требования и возможности. Он определяет семантику набора свойств Capability в этом пространстве имен. Требование - это выражение фильтра, которое утверждается в этих свойствах. Ресурс имеет набор возможностей, которые предоставляются среде выполнения при выполнении всех его требований. Задача Resolver состоит в том, чтобы найти набор ресурсов, которые бы удовлетворяли друг другу возможности и возможности, предоставляемые средой выполнения.

Например, мы добавили пространство имен osgi.ee, которое точно определяет, на какой виртуальной машине может работать пакет. Мы добавили пространство имен osgi.extender, которое моделирует зависимость от внешней программы, такой как Service Component Runtime (SCR). Большинство компонентов SCR не требуют какого-либо пакета от самого SCR, мы старались сделать их как можно более независимыми. Однако компонент SCR будет бесполезен, если только некоторый пакет во время выполнения не обеспечивает функциональность SCR. Обратите внимание, что это не может использовать Require-Bundle, потому что есть несколько реализаций SCR. Я думаю, что есть около 20 пространств имен. Каждое пространство имен определено в классе Namespace.

Эта модель дала OSGi ряд преимуществ:

  • Сплоченность Несмотря на то, что в спецификацию добавлено много пространств имен, реализации преобразователя никогда не приходилось менять, поскольку они работали над общей моделью.
  • Подробно комплекты OSGi уникальны в том, что они описывают свои зависимости очень детально. Все известные мне модульные системы, как правило, используют простую зависимость между модулями, которая не допускает подстановку.
  • Гибкость Поскольку Framework изменяет зависимости между пакетами, во время выполнения можно использовать эти зависимости. Например, в OSGi enRoute я связал пакет с его веб-страницей, проходящей по этим временным цепям.

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

Единственная неутешительная часть этого вопроса заключается в том, что я подумал, что мы довольно хорошо описали это в базовой спецификации? :-)

Ответ 2

Модель требований и возможностей является расширением модели пакета импорта/экспорта. На самом деле вы можете выразить импорт пакета как требование и экспорт пакета как возможность.

Экспорт/импорт пакетов допускает слабую связь. Вы экспортируете API, а клиент импортирует его. Таким образом, клиенту нужно знать только об API, чтобы получить слабую связь.

На более позднем этапе, когда вы собираете приложение из пакетов, это слабое соединение затрудняет автоматизацию процесса.

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

Здесь требования могут помочь. Давайте возьмем модель HTTP доски. Пакет, который хочет опубликовать сервлет, должен импортировать пакет API сервлетов, но также должен быть выражен в том, что он хочет реализовать доску osgi http.

Это может быть выражено требованием: namespace = "osgi.implementation", name = "osgi.http", version = "1.1.0". Поскольку это трудно писать вручную, есть поддержка аннотаций.

@HttpWhiteboardServletPattern("/myservlet")
@Component(service = Servlet.class)
public class MyServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        resp.getWriter().println("Hello");
    }
}

Аннотация @HttpWhiteboardServletPattern косвенно соответствует приведенному выше требованию.

Поэтому, когда вы создаете пакет с этим классом, он импортирует пакет API сервлета, а также имеет требование для реализации http доски.

Теперь, если вы посмотрите на пакет реализации, такой как служба felix http, то увидите, что он предоставляет возможность для доски объявлений.

Так что, если у вас есть OSGi-репозиторий с вашим пакетом, сервлет-API и служба felix http. Тогда распознаватель может предоставить вам полное выражение, если вы дадите ему только свой пакет.