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

Java 如何在不使用DS注释的情况下创建osgi服务的多个实例,java,osgi,osgi-ds,Java,Osgi,Osgi Ds,我已经创建了一个Osgi服务。每次服务请求到来时,我都要创建一个新的服务实例。 代码看起来像这样- @Component(immediate=true) @Service(serviceFactory = true) @Property(name = EventConstants.EVENT_TOPIC, value = {DEPLOY, UNDEPLOY }) public class XyzHandler implements EventHandler {

我已经创建了一个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声明性服务注释可以实现这一点。

但我想在不使用DS1.3的情况下实现这一点


如果不使用注释,我如何做到这一点,或者如何使用DS 1.2做到这一点?

听起来您的服务需要成为一个新的平台。这是在核心R6中引入的。来自概要R6的DS 1.3包括对待开发组件的支持


但是DS 1.2早于Core R6,因此不了解或不支持prototype scope services。

对我来说,这似乎是一个基于您认为答案是什么而不是描述您试图实现什么的问题。如果我们后退几步,就会有一个更优雅的解决方案

通常,在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;
  }
}
如果您真的不想让消费者成为EventHandler,那么将消费者注册为服务并使用白板模式让单个XyzHandler获取它将更容易:


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

我不能使用DS 1.3,因为我们使用的Equinox版本不支持它。你知道我如何用DS 1.2实现它吗?你不能用DS 1.2。
@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?
    }
  }
}