为了账号安全,请及时绑定邮箱和手机立即绑定

如何在不使用 DS 注释的情况下创建 osgi 服务的多个实例

如何在不使用 DS 注释的情况下创建 osgi 服务的多个实例

互换的青春 2021-10-28 15:46:36
我创建了一个 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 的服务实例并设置属性消费者。此外,我希望每次为每个请求创建一个新的 XyzHandler 服务实例。我发现很少有文章提到使用 osgi 声明式服务注释可以实现这一点。 OSGi如何运行一个服务的多个实例但我想在不使用 DS 1.3 的情况下实现这一点。如何在不使用注释的情况下执行此操作,或者如何使用 DS 1.2 完成此操作?
查看完整描述

2 回答

?
隔江千里

TA贡献1906条经验 获得超10个赞

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


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


@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;

  }

}

如果你真的不想让你的ConsumeranEventHandler那么将消费者注册为服务并使用白板模式让它被一个人接收仍然会更容易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在启动或停止包时跟踪需要创建/销毁的内容,并使您的代码更清晰。


查看完整回答
反对 回复 2021-10-28
?
一只斗牛犬

TA贡献1784条经验 获得超2个赞

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

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


查看完整回答
反对 回复 2021-10-28
  • 2 回答
  • 0 关注
  • 185 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信