0

我创建了一个 Osgi 服务。每次服务请求到来时,我都想为我的服务创建一个新实例。代码看起来像这样 -

    @Component(immediate=true)
    @Service(serviceFactory = true)
    @Property(name = EventConstants.EVENT_TOPIC, value = {DEPLOY, UNDEPLOY })
    public class XyzHandler implements EventHandler {
         private Consumer consumer;
         public static setConsumer(Consumer consumer) {
          this.consumer = consumer;
          }
     @Override
        public void handleEvent(final Event event) {
                consumer.notify();          
     }
 }

public class Consumer {

private DataSourceCache cache;
public void notify() {
  updateCache(cache);
  System.out.println("cache updated");
 }
public void updateCache(DataSourceCache cache) {
   cache = null;
  }
}

在我的 Consumer 类中,我想访问 XyzHandler 的服务实例并设置属性 consumer。此外,我希望每次为每个请求都创建一个 XyzHandler 的新服务实例。我发现很少有文章提到使用 osgi 声明式服务注释可以实现这一点。 OSGi如何运行一项服务的多个实例

但我想在不使用 DS 1.3 的情况下实现这一目标。

如何在不使用注释的情况下做到这一点,或者如何使用 DS 1.2 做到这一点?

4

2 回答 2

1

对我来说,这看起来像是根据您认为答案是什么而不是描述您要达到的目标提出问题的情况。如果我们退后几步,那么存在更优雅的解决方案。

一般来说,将对象注入有状态服务是 OSGi 中的一种不良模式。它迫使您对生命周期非常小心,并冒着内存泄漏的风险。从示例代码看来,您真正想要的是让您的消费者在事件管理主题上发生事件时得到通知。最简单的方法是从等式中删除 XyzHandler 并使 Consumer 成为事件处理程序,如下所示:

@Component(property= { EventConstants.EVENT_TOPIC + "=" + DEPLOY,
                       EventConstants.EVENT_TOPIC + "=" + UNDEPLOY})
public class Consumer implements EventHandler {

  private DataSourceCache cache;

  @Override
  public void handleEvent(final Event event) {
    notify();          
  }

  public void notify() {
    updateCache(cache);
    System.out.println("cache updated");
  }

  public void updateCache(DataSourceCache cache) {
       cache = null;
  }
}

如果您真的不想创建您Consumer的 an ,EventHandler那么将 Consumer 注册为服务并使用白板模式让它被一个单一的拾取仍然会更容易XyzHandler

@Component(service=Consumer.class)
public class Consumer {

  private DataSourceCache cache;

  public void notify() {
    updateCache(cache);
    System.out.println("cache updated");
  }

  public void updateCache(DataSourceCache cache) {
       cache = null;
  }
}

@Component(property= { EventConstants.EVENT_TOPIC + "=" + DEPLOY,
                       EventConstants.EVENT_TOPIC + "=" + UNDEPLOY})
public class XyzHandler implements EventHandler {

  // Use a thread safe list for dynamic references!
  private List<Consumer> consumers = new CopyOnWriteArrayList<>();

  @Reference(cardinality=MULTIPLE, policy=DYNAMIC)
  void addConsumer(Consumer consumer) {
    consumers.add(consumer);
  }

  void removeConsumer(Consumer consumer) {
    consumers.remove(consumer);
  }

  @Override
  public void handleEvent(final Event event) {
    consumers.forEach(this::notify);          
  }

  private void notify(Consumer consumer) {
    try {
      consumer.notify();
    } catch (Exception e) {
      // TODO log this?
    }
  }
}

以这种方式使用白板模式可以避免您在XyzHandler启动或停止包时需要跟踪哪些需要创建/销毁,并且会使您的代码更加简洁。

于 2018-10-09T09:04:55.230 回答
0

听起来您的服务需要是原型范围服务。这是在 Core R6 中引入的。来自 Compendium R6 的 DS 1.3 包括对作为原型范围服务的组件的支持。

但 DS 1.2 早于 Core R6,因此不了解或支持原型范围服务。

于 2018-10-06T09:56:35.147 回答