OSGi'等待听众订阅'

时间:2015-05-16 17:39:56

标签: spring osgi

假设我在捆绑包A和捆绑包B和C中的处理器(侦听器)中有一个EventGenerator服务。
A对B和C一无所知,其中处理器在初始化时订阅EventGenerator事件 可以在其他捆绑包D,E等中创建更多的侦听器。

在spring应用程序中,我会在构造Processor时进行订阅,将EventGenerator作为构造函数参数传递。我希望B和C在逻辑上依赖于A.在@PostConstruct上我会有工作系统,准备处理事件。

如何将A,B和C初始化为OSGi应用程序?当EventGenerator开始工作且处理器错过事件时,我遇到问题,因为它们尚未初始化并订阅它们。

1 个答案:

答案 0 :(得分:1)

在OSGi中,您无法实现的目标。原因是您在部署EventGenerator捆绑包时无法知道将发生哪些捆绑部署事件以及以何种顺序发生。

在Spring中,所有内容都在同一时间部署,因此可以对其进行分析,哪些bean实现了Processor接口。

有几种解决方法,您必须选择最适合您的解决方法。

<强> LogService

您可以在OSGi规范中找到日志服务章节。 LogListener 实现可以注册为OSGi服务。 LogService 实现获取每个 LogListener 服务,并为它们发送每个 LogEvents

此处的问题是,在 LogEvent 已经发生之后,可能会注册 LogListener

此处的解决方案是告知 LogService 应记录多少条记录,如果 LogListener 已注册,则发送最后的 X 事件第一。我记得, Equinox LogService 的默认设置是记住最后100个 LogEvents

类似BundleTracker的活动

BundleTracker 事件的特点是活动事件的数量有限。 事件不再相关后,将被删除。在实践中:

  • Bundle 位于容器中之前,捆绑包的最后一个事件将由每个新打开的 BundleTracker
  • 存储和处理
  • Bundle 标记为删除时,其最后一个事件将被删除

如果你有这样的事件,你可以实现相同的方法。实现它并不容易。我实施了一个库,使工作更轻松。您需要实现一些接口并通过Generics定义您的类型,您将拥有必要的事件管理功能:https://github.com/everit-org/eventdispatcher

在启动EventGenerator之前等待所有处理器

如果以前的解决方案都不适合您,您必须告诉 EventGenerator 组件不要注册其OSGi服务,直到所有处理器被选中。

在我看来,如果您通过 ConfigAdmin 进行配置,这是最好的方法。通过这样做,您将能够通过 CommandLine控制台 WebConsole 重新配置 EventGenerator 组件,而无需重新启动系统。

我实现了一个组件模型来实现这个功能。您的组件如下所示:

import org.everit.osgi.ecm.annotation.Component;
import org.everit.osgi.ecm.annotation.Service;
import org.everit.osgi.ecm.annotation.ServiceRef;
import org.everit.osgi.ecm.extender.ECMExtenderConstants

import aQute.bnd.annotation.headers.ProvideCapability;

@Component
@Service
@ProvideCapability(ns = ECMExtenderConstants.CAPABILITY_NS_COMPONENT,
    value = ECMExtenderConstants.CAPABILITY_ATTR_CLASS + "=${@class}")
public class EventGenerator {

  private Processor[] processors;

  @ServiceRef
  public void setProcessors(Processor[] processors) {
    this.processors = processors;
  }
}

您可以在组件的 processors.target 属性中使用 OSGi过滤器数组指定必要的 Processor OSGi服务。组件将启动,并在所有处理器可用后将其注册为服务。

要使上述相同的工作,您必须将以下依赖项(具有传递依赖性,小于200k)放入OSGi容器中:

<dependency>
  <groupId>org.everit.osgi</groupId>
  <artifactId>org.everit.osgi.ecm.extender.ri</artifactId>
  <version>1.0.0</version>
</dependency>

还有一个 WebConsole 插件,它显示了组件的状态(为什么它不满意或失败):

<dependency>
  <groupId>org.everit.osgi</groupId>
  <artifactId>org.everit.osgi.ecm.component.webconsole</artifactId>
  <version>1.0.0</version>
</dependency>