A компонент - это:
- активный участник системы
- , осведомленный о своей среде и адаптирующийся к ней
- environment = servicesпредоставляемые другими компонентами
- environment = resources, devices, ...
- может предоставлять услуги другим компонентам и использовать службы из других компонентов
- haveжизненный цикл
Короче говоря:
- Компонент предоставляет услуги
- Пакет управления жизненным циклом
Пакет может иметь толькоодин активатор (требуется BundleContext
), и может иметь столько активных компонентов, сколько вы хотите.
Это означает, что вы можете попытаться втиснуть в один активатор несколько проблем, связанных со свободными задачами, в один класс.
поэтому может быть проще управлять этими компонентами с помощью декларативных сервисов , через SCR («Среда выполнения сервисных компонентов», которая представляет собой «пакет расширения», реализующий новую и улучшенную OSGi R4)..2 DS - Декларативный Service - спецификация).
Это особенно верно с OSGi 4.2, потому что теперь гораздо проще записывать компоненты DS в виде POJO: методы activate
и deactivate
больше не требуются для принятия параметра ComponentContext
.См. Также Ленивая декларативная служба .
Примечание:
Это может помочь заменить эти термины в контексте OSGi и посмотреть на то, «как мы туда попали»( отличное сообщение в блоге Нила Бартлетта )
Вот некоторые важные выдержки, где «модулями» в конечном итоге становятся пакеты OSGi (управляющие Компоненты, которые объявляют Сервисы):
Разделение модулей
Нашим первым требованием является чистое разделение модулей, чтобы классы из одного модуля не имели неконтролируемой способности видеть и скрывать классы от других модулей .
В традиционной Java так называемый «путь к классам» представляет собой огромный список классов, и если несколько классов имеют одно и то же полное имя, тогда первый всегда будет найден, а второй и все остальные будут игнорироваться.
Способ предотвращения неконтролируемой видимости и затемнения классов заключается в создании загрузчика классов для каждого модуля.Загрузчик классов может загружать только те классы, о которых он знает напрямую, что в нашей системе будет содержимым одного модуля.
Уровень доступа к модулю
Еслимы останавливаемся здесь, тогда модули будут полностью изолированы и не смогут общаться друг с другом.Чтобы сделать систему практичной, нам нужно добавить возможность видеть классы в других модулях, но мы делаем это осторожно и ограниченно.
На этом этапе мы вводим другое требование: модулям нужна возможностьчтобы скрыть некоторые детали их реализации.
Мы хотели бы иметь уровень доступа «модуля», но сегодня проблема заключается в том, что компилятор javac не знает, где лежат границы модуля.
Решение, которое мы выбираем в нашей модульной системе, состоит в том, чтобы позволить модулям «экспортировать» только часть своего содержимого.Если какая-то часть модуля не экспортируется, то другие модули просто ее не видят.
При импорте мы должны импортировать то, что нам действительно нужно использовать, независимо от того, откуда он берется и игнорировать все вещи.которые упакованы вместе с ним.
Гранулярность экспорта и импорта
OSGi выбирает пакеты.
Содержимое пакета Java должно быть несколько согласованным, но не слишком обременительно перечислять пакеты как импорт и экспорт, и ничего не мешает поместить некоторые пакеты в один модуль и другие пакеты в другой модуль.
Код, который должен быть внутренним для нашего модуля, можетбыть помещены в один или несколько неэкспортированных пакетов.
Проводка пакета
Теперьу нас есть модель того, как модули изолируют себя и затем воссоединяются, мы можем представить себе создание инфраструктуры, которая создает конкретные экземпляры этих модулей во время выполнения.Он будет отвечать за установку модулей и создание загрузчиков классов, которые знают о содержимом своих соответствующих модулей.
Затем он проанализирует импорт вновь установленных модулей и попытается найти соответствующий экспорт.
Неожиданным преимуществом этого является то, что мы можем динамически устанавливать, обновлять и удалять модули.Установка нового модуля не влияет на те модули, которые уже разрешены, хотя это может позволить разрешить некоторые ранее неразрешимые модули.При удалении или обновлении фреймворк точно знает, какие модули затронуты, и при необходимости изменит их состояние.
Версии
Наша система модулей выглядит хорошо, но мыеще не может обрабатывать изменения, которые неизбежно происходят в модулях с течением времени.Нам нужно поддерживать версии.
Как мы это делаем?Во-первых, экспортер может просто указать некоторую полезную информацию о пакетах, которые он экспортирует: «это версия 1.0.0 API».Импортер теперь может импортировать только ту версию, которая совместима с ожидаемой и скомпилированной / протестированной, и отказывается принимать
Упаковочные модули и метаданные
Нашимодульной системе понадобится способ упаковать содержимое модуля вместе с метаданными, описывающими импорт и экспорт в развертываемый блок.
Таким образом, единственный вопрос заключается в том, куда мы должны поместить метаданные, то есть списки импорта.и экспорт, версии и так далее?
Как оказалось, OSGi была разработана до 2000 года, поэтому она выбрала одно из этих решений.Вместо этого он оглянулся назад на Спецификацию файла JAR, где прописан ответ:
META-INF/MANIFEST.MF
- стандартное расположение для произвольных метаданных приложения.
Позднее связывание
Последний кусок модульной головоломки - поздняя привязка реализаций к интерфейсам.Я бы сказал, что это ключевая особенность модульности, даже если некоторые модульные системы полностью ее игнорируют или, по крайней мере, считают ее вне области применения.
Мы должны искать децентрализованный подход .
Вместо того, чтобы говорить, что делать классом Бога, давайте предположим, что каждый модуль может просто создавать объекты и публиковать их где-то, чтобы другие модули могли их найти.Мы называем эти опубликованные объекты «сервисами», а место, где они публикуются, «реестром сервисов».
Наиболее важной информацией о сервисе является интерфейс (или интерфейсы), который он реализует, поэтому мы можем использовать его в качествепервичный регистрационный ключ.
Теперь модуль, которому нужно найти экземпляры определенного интерфейса, может просто запросить реестр и выяснить, какие службы доступны в это время.Сам реестр все еще является центральным компонентом, существующим вне какого-либо модуля, но он не «Бог»… скорее, он похож на общую доску.