OSGi AspectService получает свойства службы аспектированной службы

Учитывая сервис Sender со свойствами и сервис аспектов LogSender, как LogSender получает свойства сервиса текущего Sender? Я хотел бы добавить свойство, чтобы дополнительно регистрировать данные, которые отправляет конкретный Sender.

component.getServiceProperties();, кажется, возвращает свойства службы LogSender вместо свойств Sender.

Я просмотрел ConfigAdmin, но не вижу способа связать Sender, аспектированный LogSender, с конкретной используемой конфигурацией.

Я использую Apache Felix в качестве контейнера OSGi, если это уместно.

Вот метод init Activator после добавления ConfigurationAdmin в список зависимостей.

public void init(BundleContext context, DependencyManager manager) throws Exception {
     manager.add(createAspectService(Sender.class, null, 10).setImplementation(LogSender.class)
            .add(createServiceDependency().setService(ConfigurationAdmin.class)
                    .setRequired(true)));
            .add(createServiceDependency().setService(LogService.class).setRequired(true)));
}

person Rob Paisley    schedule 20.01.2018    source источник


Ответы (1)


Чтобы внедрить служебные свойства оригинального Sender в аспект LogSender, вы можете использовать подпись в DependencyActivatorBase (или DependencyManager), которая позволяет указать методы обратного вызова аспекта LogSender "добавить/изменить/удалить":

DependencyActivatorBase.createAspectService(
    Class<?> serviceInterface,
    String serviceFilter,
    int ranking,
    String add,
    String change,
    String remove);

Затем сигнатура метода обратных вызовов LogSenderAspect может принимать в качестве аргументов службу Sender, а также карту свойств службы Sender.

Теперь второе (более простое) решение — указать сервисный фильтр для вашего аспекта, и в этом случае; нет необходимости указывать какие-либо обратные вызовы.

давайте взглянем на первое решение с обратными вызовами, где аспект LogSender определяет метод «setSender (Sender, Map)», и тогда этот аспект будет регистрировать только метод «send» служб Sender, имеющих свойства службы «foo = bar» (здесь мы игнорируем обратные вызовы изменения/удаления сервиса):

public class Activator extends DependencyActivatorBase{
    public void init(BundleContext ctx, DependencyManager dm) throws Exception {
        Component logSender = createAspectService(Sender.class, null, 10, "setSender", null, null)
                .setImplementation(LogSender.class)    
                .add(createServiceDependency().setService(LogService.class).setRequired(true));
        dm.add(logSender);         
    }
}

class LogSender implements Sender {     
    volatile Sender sender;
    volatile Map<String, Object> senderProperties;
    volatile LogService log;

    void setSender(Sender sender, Map<String, Object> senderProperties) {
        this.sender = sender;
        this.senderProperties = senderProperties;
    }

    @Override
    public void send() {
        if ("bar".equals(senderProperties.get("foo"))) {
            log.log(LogService.LOG_DEBUG, "calling method send called on Sender service having properties foo=bar");
        }
        this.sender.send();         
    }       
}

Теперь более простое решение состоит в использовании служебного фильтра "(foo=bar)" при определении вашего аспекта, и в этом случае нет необходимости использовать обратный вызов:

public class Activator extends DependencyActivatorBase{
    public void init(BundleContext ctx, DependencyManager dm) throws Exception {
        Component logSender = createAspectService(Sender.class, "(foo=bar)", 10)
                .setImplementation(LogSender.class)    
                .add(createServiceDependency().setService(LogService.class).setRequired(true));
        dm.add(logSender);         
    }
}

class LogSender implements Sender {     
    volatile Sender sender;

    @Override
    public void send() {
        log.log(LogService.LOG_DEBUG, "calling method send called on Sender service having properties foo=bar");
        this.sender.send();
    }       
}

это помогает? /Пьер

person Pierre De Rop    schedule 21.01.2018
comment
Клянусь, я пробовал версию обратного вызова с тремя аргументами и не заставил ее работать, и единственное, что я думал, было другим, это то, что я использовал Dictionary<String, Object> вместо Map<String, Object>, но повторная попытка только сейчас показывает, что она работает в любом случае. Я не знаю, что я сделал по-другому раньше, но важно то, что теперь это работает. - person Rob Paisley; 22.01.2018