Передача параметров времени выполнения службе в аннотациях OSGi felix scr

Я работаю над приложением OSGi (с аннотациями felix scr), которое предоставляет услугу. Служба регистрируется с помощью внешнего API, передавая строковые значения.

listener.addSchemaChangeListener(new ChangeListener()
{
    @Override
    public void schemaChange(ChangeEvent changeEvent)
    {
        String schemaName = changeEvent.getSchemaName();

        if (null != myBuilder && schemaList.contains(schemaName))
        {
            initVariables();
        }
    }
}, "SCHEMA1");

Служба использует приведенный выше фрагмент кода для регистрации слушателей для нескольких значений «SCHEMA1», «SCHEMA1», «SCHEMA3» ... Я планирую повторно использовать эту службу в различных пакетах. Но я хочу слушать только изменения SCHEMA1, а не все.

@Reference (name = "ServiceListener" ", policy = ReferencePolicy.DYNAMIC, cardinality = ReferenceCardinality.MANDATORY_UNARY, bind =" bind ", unbind =" unbind ", referenceInterface = ServiceListener.class) private AtomicReference myServiceListener = new AtomicReference‹> () ;

Если я попытаюсь использовать его в другой службе с @Reference, тогда не будет возможности передавать значения службе для прослушивания только определенных изменений схемы, чтобы служба могла быть возобновлена ​​в моем пакете, передавая только список схемы для прослушивания вместо все. Потому что метод активации будет вызван после того, как служба будет правильно привязана к классу использования (компоненту). Есть ли в OSGi какие-либо положения для реализации этой функции?


person Shriram    schedule 14.07.2017    source источник


Ответы (2)


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

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

Выкройка на доске довольно проста. Вместо того, чтобы заставлять каждого слушателя искать сервис и регистрироваться в нем, вы инвертируете модель. Источник событий (в данном случае изменения схемы) ищет службы прослушивателя, зарегистрированные в реестре служб OSGi. Таким образом, слушатели легко писать и фильтровать, и нет беспорядочной и подверженной ошибкам логики добавления / удаления слушателя в код.

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

Слушатель 1 (слушает изменения для SCHEMA1)

@Component(
    property="schemaName=SCHEMA1")
public class MyListener implements ChangeListener {
    // Your implementation in here
}

Слушатель 2 (прослушивает изменения для SCHEMA1, SCHEMA2 и SCHEMA3)

@Component(
    property={"schemaName=SCHEMA1",
              "schemaName=SCHEMA2",
              "schemaName=SCHEMA3"})
public class MyListener implements ChangeListener {
    // Your implementation in here
}

Пример Источник событий для Schema1:

@Component
public class MyListener implements ChangeListener {

    @Reference(policy=DYNAMIC, target="(schemaName=SCHEMA1)")
    private final List<ChangeListener> listeners = new CopyOnWriteArrayList<>();

    private void onSchemaChange(ChangeEvent event) {
        listeners.forEach(l -> l.schemaChange(event);
    }

    // Rest of your implementation in here
}
person Tim Ward    schedule 17.07.2017

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

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

person Christian Schneider    schedule 15.07.2017