Приоритезация выбора OSGi в контейнере, когда существует более одной реализации
Я играю с OSGi и имею несколько пакетов. Bundle A и B содержат зарегистрированный сервис, который реализует один интерфейс. Третий пакет C включает код для поиска службы, реализующей ранее упомянутый интерфейс. У пучков A и B разные номера версий, однако, похоже, что C получает услугу из первого запущенного пакета. Я изменил начальный уровень, чтобы сделать правильную вещь, но версия используется только для принятия, а не для заказа службы.
A version 1.0 start level 1
B version 1.1 start level 2
C requires both bundles, start level 3
В приведенном выше примере C всегда получает услугу от A, хотя B имеет более высокую версию пакета. Однако, если я переключу начальный уровень, так что B начинается до A, C видит службу B.
Я искал веб-сайт OSGi, и нет четкого объяснения того, используется ли управление версиями пакета для приоритизации службы над другой. Мое понимание, похоже, указывает на то, что начальный уровень должен использоваться для упорядочивания пуска, чтобы можно было правильно усвоить зависимости. Однако он, похоже, перегружен, так что он также приоритизирует приоритет службы. Учитывая все вышеизложенное, я предполагаю, что имеет смысл не использовать версию пакета в выборе, потому что номер версии - это просто число относительно ничего.
Каков наилучший способ определить приоритет одной службы над другой, помимо начального уровня?
Ответы
Ответ 1
Лучший способ определения приоритетности служб OSGi для использования SERVICE_RANKING свойства сервиса. Это свойство может предоставляться в объекте properties
, переданном
метод BundleContext.registerService().
В соответствии с документацией метода BundleContext.getServiceReference():
Если существует несколько таких служб, возвращается сервис с наивысшим рейтингом (как указано в свойстве Constants.SERVICE_RANKING).
Если есть рейтинг в рейтинге, служба с наименьшим идентификатором службы (как указано в свойстве Constants.SERVICE_ID); то есть служба, которая была зарегистрирована первой, возвращается.
Ответ 2
Если служба зарегистрирована сторонней библиотекой, вы не можете контролировать ее ранжирование или зарегистрированные свойства. Использование ServiceTracker
дает вам больше контроля.
Например, вы можете сделать что-то вроде этого:
ServiceTracker tracker = new ServiceTracker (bundleContext, serviceClass ,new ServiceTrackerCustomizer () {
@Override
public Object addingService(ServiceReference srvRef) {
boolean criteria = // whatever your criteria is for prioritizing
if(criteria)
return bundleContext.getService(srvRef);
else
return null;
}
@Override
public void modifiedService(ServiceReference srvRef, Object arg1) {
}
@Override
public void removedService(ServiceReference srvRef, Object arg1) {
}
});
tracker.open();
Object service = tracker.getService();
Ответ 3
В org.osgi.framework.BundleContext.registerService(String[], Object, Dictionary)
вы можете указать произвольные свойства в Dictionary
. Чтобы найти услугу, вы можете указать фильтр в org.osgi.framework.BundleContext.getServiceReferences(String, String)
. И если этого недостаточно, вы можете проверить org.osgi.framework.ServiceReference.getProperty(String)
, например, для значения приоритета.