【问题标题】:OSGi 'await for listeners to subscribe'OSGi '等待听众订阅'
【发布时间】:2015-05-16 17:39:56
【问题描述】:

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

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

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

【问题讨论】:

  • 如果你可以通过 ConfigAdmin 配置 EventGenerator 在发送第一个事件之前等待指定的处理器,我可以举个例子。
  • 我认为 EventGenerator 从架构的角度了解它的听众是错误的。可以随时添加另一个捆绑侦听器。不应更改 EventGenerator 包。
  • 我的意思是一个可配置的组件。这意味着只需要更改配置(通过 configadmin),而不需要更改 EventGenerator 捆绑包本身。在实践中:当您想要一个新的处理器时,您将捆绑包放入包含处理器的 OSGi 容器中,然后打开 Web 控制台并将新处理器添加到配置屏幕上的 EventGenerator(或者您进行配置更新如果您编写一些部署代码,则以编程方式)
  • 你提出了类似控制器的东西,它应该知道 EventGenerator 和侦听器,它应该设法进行订阅并在完成时自行启动 EventGenerator。这肯定会奏效,但这种架构也很僵化。我正在寻找的是一种 @PostConstruct 回调,不仅是在当前包中构造的 Spring bean,而且在 OSGi 应用程序的所有包中。我会在 bean/服务构造上完成所有需要的订阅,并在 ProerptiesSet() 之后开始处理事件。这将只需要监听器对 EventGenerator 的逻辑依赖。
  • “但在 OSGi 应用程序的所有捆绑包中”:您无法不知道 OSGi 应用程序中有多少捆绑包。您无法知道捆绑包是否在运行时被替换。如果您使用 Spring,所有知识都在一个框架内,并且该框架只能作为一个单元重新部署。如果您使用 OSGi,您的应用程序是模块化的,并且这些模块有自己的生命周期。你不能在 OSGi 中拥有像 @PostConstruct 这样的功能,因为没有一切准备就绪和修复的状态。

标签: spring osgi


【解决方案1】:

你想要达到的目标在 OSGi 中是不可能的。原因是你在部署EventGenerator的bundle的时候无法知道,会发生什么bundle部署事件,以什么顺序发生。

在 Spring 中,所有东西都是同时部署的,因此可以分析哪些 bean 实现了处理器接口。

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

日志服务

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

这里的问题是 LogListener 可能在 LogEvent 已经发生之后被注册。

这里的一个解决方案是告诉LogService应该记住多少条记录,如果注册了一个LogListener,发送最后一个X个事件第一的。据我所知,Equinox LogService 的默认设置是记住最后 100 个 LogEvents

BundleTracker 类事件

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

  • 直到 Bundle 在容器中,每个新打开的 BundleTracker 都会存储和处理该包的最后一个事件
  • Bundle 被标记为删除时,它的最后一个事件被删除

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

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

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

在我看来,最好的方式是通过 ConfigAdmin 进行配置。通过这样做,您将能够通过 CommandLine ConsoleWebConsole 重新配置您的 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>

【讨论】:

    猜你喜欢
    • 2012-05-30
    • 1970-01-01
    • 2021-05-06
    • 2021-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-20
    相关资源
    最近更新 更多