OSGi является спецификацией, и наиболее распространенными реализациями можно считать Equinox , Apache Felix и Knoplerfish . В этой статье я попытаюсь привести пример создания простого пакета OSGi в Equinox .
Структура OSGi

Базовую структуру OSGi можно увидеть на рисунке справа. Реализации OSGi находятся на вершине JVM и предоставляют механизмы для управления службами, определения компонентов, выполнения, управления и контроля жизненного цикла модулей. Наиболее важные концепции OSGi описаны ниже:
Bundle
В системах OSGi компонентам, которые создают структуру, присваивается имя « Bundle ». На этапе развертывания каждый пакет OSGi представляет собой файл JAR . Но основное отличие файлов jar-пакетов с обычными можно считать определением манифеста для OSGi и некоторыми классами для OSGi. Мы обсудим эти различия в следующих разделах и в примере.
Сервисы
Сервисы обеспечивают взаимодействие между узлами структуры. Сервисы представляются как интерфейсы и регистрируются в реализации, которая выполняет этот интерфейс. Параллельно со структурой SOA наличие доступа через сервисы OSGi делает системы на основе OSGi более свободными по сравнению с обычными jav-структурами на основе jar. Эта структура также позволяет изменять компоненты системы во время выполнения.
OSGi реализует сервисный каталог для сервисов, которые должны быть зарегистрированы и доступны через. OSGi также предоставляет механизмы управления сервисами.
Жизненный цикл
OSGi предоставляет платформу, которая позволяет контролировать жизненный цикл комплектов. В этой структуре каждый пакет имеет свою собственную конфигурацию OSGi, в основном с точки зрения зависимостей и открытых частей, и система управляется самой OSGi. OSGi знает комплекты, которые составляют систему, которая предоставляется с файлом конфигурации с заказом, и управление жизненным циклом применяется для каждого из компонентов с данным заказом. Сторона пакета управления жизненным циклом управляется классом «Activator», который реализует интерфейс OSGi, который должен существовать в каждом «обычном» пакете OSGi. (Не для «фрагментированных», но пока это выходит за рамки данной статьи, забудьте об этом)
Связки
Как упомянуто выше, b undle — это файл jar, который имеет по крайней мере класс Activator и файл MANIFEST, в котором есть специфичные для OSGi заголовки и информация. Образец файла MANIFEST можно увидеть ниже. Давайте посмотрим на значение каждой части в определении.
|
1
2
3
4
5
6
7
8
|
Bundle-Name: Our BundleBundle-SymbolicName: us.elron.bundles.oursBundle-Description: Very own bundle of oursBundle-ManifestVersion: 1Bundle-Version: 1.0.0Bundle-Activator: us.elron.bundles.ours.BundleActivatorExport-Package: us.elron.bundles.ours.exported; version = "1.0.0"Import-Package: us.elron.bundles.yours.exported; version = "1.3.0" |
- Bundle-Name : «привлекательное для публики» имя пакета.
- Bundle-SymbolicName: как единственное обязательное определение в файле MANIFEST, символическое имя определяет уникальное имя пакета в экосистеме OSGi. Поскольку это определение должно быть уникальным, оно обычно определяется как имя базового пакета для данного соглашения.
- Описание пакета : описание «raison d’être» пакета.
- Bundle-ManifestVersion: версия манифеста пакета.
- Bundle-Version: версия пакета OSGi.
- Bundle-Activator: этот класс используется для управления жизненным циклом пакета. Этот класс вызывается OSGi для запуска или остановки пакета.
- Export-Package. В этом разделе определяются пакеты, которые должны использоваться другими пакетами.
- Import-Package: пакеты, необходимые для выполнения текущего пакета, определены в этом разделе.
Жизненный цикл
Структура OSGi обеспечивает необходимые механизмы для управления жизненным циклом комплектов. Пакеты подлежат OSGi для контроля их жизненных циклов в соответствии с заданной конфигурацией. Этапы жизненного цикла подробно объясняются ниже:
|
СОСТАВЛЯЮЩИЙ СТАТУС
|
ОПИСАНИЕ
|
|---|---|
|
УСТАНОВЛЕНЫ
|
Это состояние указывает, что шаг установки был успешно завершен. В этом случае не выполняется ни анализ зависимостей, ни загрузка классов. Выполняются только необходимые шаги, такие как определение свойств пакета, анализируя его файл манифеста. |
|
ПОСТАНОВИЛИ
|
Пакет находится в этом состоянии, когда OSGi разрешает и удовлетворяет все свои зависимости и выполняет операции загрузки классов. Это состояние, которое наступает до запуска и после остановки. |
|
ЗАПУСК
|
Это состояние, в котором пакет обнаружен, когда вызывается метод «start» Активатора пакета, но еще не завершенный успешно или неудачно. |
|
ACTIVE
|
Пакет успешно запущен и работает, что означает, что метод «Activator» привел к успеху. |
|
ОСТАНОВКА
|
Это состояние, в котором пакет обнаружен, когда вызывается метод «стоп» Активатора пакета, но еще не завершенный успешно или неудачно. |
|
Uninstalled
|
Это состояние, когда пакет удаляется из системы. В этой ситуации нет перехода в другое состояние. Компонент должен быть установлен снова. |
Давайте сделаем простой пример, чтобы прояснить упомянутые концепции и шаги выше. В нашем примере будет два пакета, один из которых предоставляет службу генератора случайных чисел для генерации случайных чисел, а другой пакет будет использовать эту службу для печати случайного числа каждую секунду с отдельным процессом. (Не имеет смысла? То же самое для меня, но достаточно, чтобы понять концепции )
Теперь давайте разработаем этот пример проекта (желательно) вместе, используя Eclipse и Equinox.
В Eclipse комплекты OSGi разрабатываются с помощью мастера New Plug-in Project, как показано ниже:
С помощью мастера создайте два проекта ( us.elron.osgi.random и us.elron.osgi.user ), выполнив необходимые шаги и назовите ваши пакеты и Activators ( RandomActivator , UserActivator ), как показано ниже. Конечный результат проекта также должен быть таким:
Определения служб, реализации и определения MANIFEST пакета, генерирующего случайные числа ( us.elron.osgi.random ), приведены ниже.
Интерфейс (IRandomGenerator):
|
1
2
3
4
5
6
7
8
9
|
package us.elron.osgi.random;public interface IRandomGenerator { int generate (); int generate(int upperBound);} |
Сервис (RandomGenerator):
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package us.elron.osgi.random.generator;import java.util.Random;import us.elron.osgi.random.IRandomGenerator;public class RandomGenerator implements IRandomGenerator { private final Random random; public RandomGenerator () { this.random = new Random(); } @ Override public int generate () { return this.random.nextInt(); } @ Override public int generate (final int upperBound) { return this.random.nextInt (upperBound); }} |
Активатор (RandomActivator) :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
package us.elron.osgi.random;import org.osgi.framework.BundleActivator;import org.osgi.framework.BundleContext;import us.elron.osgi.random.generator.RandomGenerator;public class RandomActivator implements BundleActivator { public void start(final BundleContext context) throws Exception { System.out.println("[Random] Let's 'Random'!"); RandomGenerator randomGenerator = new RandomGenerator(); context.registerService(IRandomGenerator.class.getName (), randomGenerator, null); System.out.println("[Random] Random services were registered."); } public void stop(final BundleContext context) throws Exception { System.out.println("[Random] Bundle is being stopped !"); }} |
Описание компонента MANIFEST.MF будет следующим. Пакет должен по крайней мере экспортировать пакеты, которые имеют свои сервисные интерфейсы, чтобы использовать их в других пакетах. Поскольку слабая связь является одной из наиболее важных целей систем SOA и OSGi, из любого пакета следует экспортировать только минимально необходимый набор классов.
|
01
02
03
04
05
06
07
08
09
10
11
|
Manifest-Version: 1.0Bundle-ManifestVersion: 2Bundle-Name: RandomBundle-SymbolicName: us.elron.osgi.randomBundle-Version: 1.0.0.qualifierBundle-Activator: us.elron.osgi.random.RandomActivatorBundle-Vendor: ELRON.USRequire-Bundle: org.eclipse.core.runtimeBundle-RequiredExecutionEnvironment: JavaSE-1.6Bundle-ActivationPolicy: lazyExport-Package: us.elron.osgi.random |
Как можно видеть, сервис является реализацией интерфейса Java, зарегистрированного как сервис OSGi. Класс Activator — это точка доступа OSGi пакета. OSGi использует класс Activator пакета для управления его жизненным циклом. При этом OSGi отправляет реализацию пакета « org.osgi.framework.BundleContext » в комплект. Этот интерфейс позволяет связке взаимодействовать со слоем OSGi и, как видно из кода, выполнять такие операции, как регистрация и получение службы OSGi.
Теперь давайте посмотрим на классы пользовательских пакетов:
Это класс, который печатает случайные числа, сгенерированные службой генератора случайных чисел.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
package us.elron.osgi.user;import us.elron.osgi.random.IRandomGenerator;public class RandomPrinter extends Thread { private final IRandomGenerator random; private volatile boolean run = true; public RandomPrinter (final IRandomGenerator random) { this.random = random; } @ Override public void run () { while (this.run) { System.out.println ("[User] new random number: " + this.random.generate (300)); try { Thread.sleep (1000); } catch (final InterruptedException e) { break; } } System.out.println ("[User] The process was terminated."); } public void close () { this.run = false; }} |
и это реализация Activator:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
package us.elron.osgi.user;import org.osgi.framework.BundleActivator;import org.osgi.framework.BundleContext;import org.osgi.framework.ServiceReference;import us.elron.osgi.random.IRandomGenerator;public class UserActivator implements BundleActivator { private RandomPrinter randomPrinter; public void start (final BundleContext context) throws Exception { System.out.println ("[User] Here we go .."); ServiceReference randSrvRef = context.getServiceReference (IRandomGenerator.class.getName ()); IRandomGenerator randService = (IRandomGenerator) context.getService (randSrvRef); if (randService == null) { throw new Exception ("[User] Error! Random service could not be found!"); } this.randomPrinter = new RandomPrinter(randService); this.randomPrinter.start(); } public void stop (final BundleContext bundleContext) throws Exception { System.out.println ("[User] finish .."); this.randomPrinter.close (); }} |
MANIFEST.MF описание «пользовательского» пакета будет следующим. Мы должны определить зависимость с помощью пакета случайных генераторов «us.elron.osgi.random», в котором находится интерфейс произвольного сервиса. Зависимости могут быть определены на уровне пакета или пакета, однако, чтобы уменьшить зависимости между пакетами, лучше всего лучше использовать зависимость на уровне пакета.
|
01
02
03
04
05
06
07
08
09
10
11
|
Manifest-Version: 1.0Bundle-ManifestVersion: 2Bundle-Name: UserBundle-SymbolicName: us.elron.osgi.userBundle-Version: 1.0.0.qualifierBundle-Activator: us.elron.osgi.user.UserActivatorBundle-Vendor: ELRON.USRequire-Bundle: org.eclipse.core.runtimeBundle-RequiredExecutionEnvironment: JavaSE-1.6Bundle-ActivationPolicy: lazyImport-Package: us.elron.osgi.random |
Чтобы запустить эти проекты в OSGi с использованием Eclipse, необходимо определить конфигурацию запуска, как показано ниже. На шаге « Запуск (или отладка ) конфигураций » в OSGi Framework необходимо создать новую конфигурацию (щелкнув правой кнопкой мыши) и выбрать новые комплекты в этой конфигурации. Чтобы предоставить необходимые зависимости для выбранных пакетов, мы можем использовать «Добавить необходимые пакеты». ». Таким образом, Eclipse разрешит иерархию зависимостей и добавит необходимые пакеты для выбранных. Мы также должны определить порядок запуска пакетов. Этот порядок должен быть определен в соответствии с зависимостями комплектов. Зависимые пакеты должны начинаться после пакетов, от которых они зависят. Итак, в нашем примере мы установим уровень «us.elron.osgi.random» на 1 , а « us.elron.osgi.user » установим на 2 .
Выполнение проекта с этой формой создает вывод, как показано ниже:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
OSGi> [Random] Let's 'Random'![Random] Random services were registered.[User] Here we go ..[User] new random number: 38[User] new random number: 250[User] new random number: 94[User] new random number: 150[User] new random number: 215[User] new random number: 124[User] new random number: 195[User] new random number: 260[User] new random number: 276[User] new random number: 129 |
OSGi Runtime предоставляет консольный интерфейс для взаимодействия с самим собой. При запуске окна приложения консоли мы видим сценарий «osgi>» , который говорит, что мы можем получить доступ к консоли. После упоминания о нескольких важных командах, которые вы можете выполнить в консоли, я оставлю вас наедине с консолью, чтобы вы могли узнать, что там можно сделать, начиная с команды «help» .
Команда «ss» показывает все компоненты, зарегистрированные в OSGi, с их значениями id , состояния и имени пакета вместе с версией версии . Значение id указывает уникальный идентификатор, данный OSGi каждому пакету. Это число остается неизменным при выполнении JVM, даже если пакет удален и установлен снова (одна вещь, которую нужно обнаружить), но его можно изменить в новом исполнении. Значения состояния указывают на состояние пакета (подробно и объяснено в таблице выше), а значения name и version указывают на то, что их имена вызывают у нас. Для текущей системы вывод команды «ss» выглядит следующим образом:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
OSGi> ssFramework is launched.id State Bundle0 ACTIVE org.eclipse.osgi_3.6.0.v20100517 Fragments = 42 ACTIVE org.eclipse.core.jobs_3.5.0.v201005153 ACTIVE javax.servlet_2.5.0.v200910301333 Resolved javax.transaction_1.1.1.v201006150915 4 Master = 05 ACTIVE org.eclipse.core.runtime_3.6.0.v201005056 ACTIVE org.eclipse.equinox.preferences_3.3.0.v201005037 ACTIVE org.eclipse.osgi.services_3.2.100.v201005038 ACTIVE org.eclipse.core.runtime.compatibility.auth_3.2.200.v201005179 ACTIVE us.elron.osgi.random_1.0.0.qualifier Resolved org.eclipse.core.runtime.compatibility.registry_3.3.0.v20100520 10 Master = 1111 ACTIVE org.eclipse.equinox.registry_3.5.0.v20100503 Fragments = 1012 ACTIVE org.eclipse.equinox.app_1.3.0.v2010051213 ACTIVE org.eclipse.equinox.common_3.6.0.v2010050314 ACTIVE org.eclipse.core.contenttype_3.4.100.v20100505 14-123515 ACTIVE us.elron.osgi.user_1.0.0.qualifierOSGi> |
Давайте предположим, что мы хотим отключить наш пользовательский пакет. В этом случае нам нужно выполнить команду «stop» с идентификатором пакета, который мы хотим остановить (в данном случае 15).
|
1
2
3
4
5
|
[User] a new random number is: 48[User] a new random number is: 49OSGi> stop 15[User] finish ..[User] The process was terminated. |
Когда мы снова посмотрим на вывод команды «ss» ,
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
Framework is launched.id State Bundle0 ACTIVE org.eclipse.osgi_3.6.0.v20100517 Fragments = 42 ACTIVE org.eclipse.core.jobs_3.5.0.v201005153 ACTIVE javax.servlet_2.5.0.v200910301333 Resolved javax.transaction_1.1.1.v201006150915 4 Master = 05 ACTIVE org.eclipse.core.runtime_3.6.0.v201005056 ACTIVE org.eclipse.equinox.preferences_3.3.0.v201005037 ACTIVE org.eclipse.osgi.services_3.2.100.v201005038 ACTIVE org.eclipse.core.runtime.compatibility.auth_3.2.200.v201005179 ACTIVE us.elron.osgi.random_1.0.0.qualifier Resolved org.eclipse.core.runtime.compatibility.registry_3.3.0.v20100520 10 Master = 1111 ACTIVE org.eclipse.equinox.registry_3.5.0.v20100503 Fragments = 1012 ACTIVE org.eclipse.equinox.app_1.3.0.v2010051213 ACTIVE org.eclipse.equinox.common_3.6.0.v2010050314 ACTIVE org.eclipse.core.contenttype_3.4.100.v20100505-123515 RESOLVED us.elron.osgi.user_1.0.0.qualifier |
мы видим, что состояние пользовательского пакета с идентификатором 15 установлено (см. раздел «Жизненный цикл»). Аналогично, мы можем выполнить команду запуска (запуск 15), чтобы запустить пакет и наблюдать, как процесс начал работать снова, или выполнить команду « s », чтобы просмотреть все службы, зарегистрированные в OSGi, или использовать команду удаления для удаления пакета из OSGi . Вы можете обнаружить!
В этой статье я попытался просто объяснить, что такое OSGi , как он работает и что с ним можно сделать. Надеюсь, тебе понравится. Вы можете скачать источники здесь .
Не стесняйтесь комментировать или связаться через elron [at] elron.us. Я буду рад услышать от вас.
Ссылка: OSGi: Введение от нашего партнера JCG Элрона в блоге Ender Ayd? N Orak .
Статьи по Теме :



