假设我在捆绑包A和捆绑包B和C中的处理器(侦听器)中有一个EventGenerator服务。
A对B和C一无所知,其中处理器在初始化时订阅EventGenerator事件
可以在其他捆绑包D,E等中创建更多的侦听器。
在spring应用程序中,我会在构造Processor时进行订阅,将EventGenerator作为构造函数参数传递。我希望B和C在逻辑上依赖于A.在@PostConstruct上我会有工作系统,准备处理事件。
如何将A,B和C初始化为OSGi应用程序?当EventGenerator开始工作且处理器错过事件时,我遇到问题,因为它们尚未初始化并订阅它们。
答案 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 事件的特点是活动事件的数量有限。 事件不再相关后,将被删除。在实践中:
如果你有这样的事件,你可以实现相同的方法。实现它并不容易。我实施了一个库,使工作更轻松。您需要实现一些接口并通过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>