java - 我应该保持 OSGi ServiceTracker 打开,还是在使用后关闭它?

标签 java osgi apache-felix

ServiceTracker 中使用 OSGi BundleActivator 的最佳实践是什么?我在网上看到过一些例子,它们在 start 方法中打开一个跟踪器,将它存储在一个实例变量中,然后在 stop 方法中关闭它,并在包的生命周期内保持打开状态。这合适吗?我一直在编写代码,在需要时打开跟踪器,获取服务并使用它,然后关闭跟踪器。当然,如果我想在以后使用它,这需要将 BundleContext 本身存储在一个实例变量中。由于我必须存储一个或另一个,因此我存储的可能没有太大区别。

在一个相关的问题中,如果我每次需要时都打开跟踪器,是否有必要在使用从它获得的服务时保持打开状态,或者我可以打开跟踪器、获取服务、关闭跟踪器,然后使用服务?在使用该服务之前,我认为没有理由无法关闭跟踪器。

最佳答案

服务来来去去——作为 OSGi 开发人员,您的责任是仅在服务已通过捆绑包发布时使用服务,更重要的是在未发布时发布服务。如果在取消发布后继续使用服务,则可能会发生不可预测的错误。至少,您会导致与该服务实例关联的堆空间被固定在内存中,这会破坏 OSGi 动态安装和卸载包的能力。

所以,你问你是否应该在使用服务之前关闭 ServiceTracker:我的回答是 NO 。 ServiceTracker 充当当前服务的“智能指针”,它管理所有监听器等,以便在服务消失时得到通知。如果您关闭跟踪器,那么您将不再了解服务的状态,那么您如何知道它是否仍然有效?

使用 ServiceTracker 的理想模式——假设跟踪器始终保持打开状态——如下:

{    
    Service svc = tracker.getService();
    svc.doSomething();
}
// 'svc' is now forgotten, and may be garbage collected

也就是说,当您在跟踪器上调用 getService() 时,您将获得实际服务的实例,但您应该快速使用它,然后尽快忘记它。您绝对不能将 getService() 的结果存储在一个字段中并长时间保留它。

至于是否应该只在需要时才打开和立即关闭跟踪器——不,绝对没有必要这样做。一个开放的跟踪器不消耗任何重要的资源,它只是意味着它被注册为一个监听器,以便它知道服务何时来来去去。事实上,重复打开和关闭跟踪器是低效的,因为每次打开它时,它都必须根据服务注册表的当前状态同步自身。这就是为什么您在示例中看到的模式通常是在捆绑激活期间打开跟踪器并保持打开状态……这是最好的模式。

顺便说一句,也不需要在 BundleActivator.stop 方法中显式关闭跟踪器。当您的捆绑包停止时,与您的跟踪器关联的所有资源都将被自动清理。明确关闭的唯一原因是,如果您有多个跟踪器和/或服务注册,并且您想控制清理的顺序。

说了以上所有之后,我要扔手榴弹了: 请停止使用 ServiceTracker ! 这是一个非常低级的实用程序,很少需要,并且只在“管道”或基础设施代码中使用。您的大部分应用程序都应该使用更高级别的抽象来构建。我强烈建议使用声明式服务,这比使用 ServiceTrackers 容易得多。

关于java - 我应该保持 OSGi ServiceTracker 打开,还是在使用后关闭它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18521376/

相关文章:

java - validator 类内的依赖项未在单元测试中初始化

java多态创建对象

java - 用于添加全局存储的 Kafka 流用例

java - Apache Felix - 如何保证在激活方法之前注入(inject)动态引用

OSGI 中的 Java 货币引用实现

java - Maven - Unresolved 对 [javax.activation, javax.annotation] 的引用

java - OSGi JAR 一旦运行,是否可以要求其容器从另一个位置加载另一个 OSGi JAR?

java - 菲利克斯/OSGi : How to use SCR components that are not OSGi services?

java - Spring Boot 应用程序无法在 Elastic Beanstalk 上启动

java - 在 maven osgi 包中使用外部库 (jar) [netbeans]