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

Joh*_*ons 3 java osgi apache-felix

在一个OSGi ServiceTracker中使用OSGi的最佳做法是BundleActivator什么?我在Web上看到了在start方法中打开跟踪器的示例,将其存储在实例变量中,并在stop方法中关闭它,使其在捆绑的生命周期中保持打开状态.这个合适吗?我一直在编写代码,只要我需要它就打开跟踪器,获取服务并使用它,然后关闭跟踪器.当然,BundleContext如果我想在以后使用它,则需要将自身存储在实例变量中.因为我必须存储一个或另一个,所以我存储的差别可能不大.

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

Nei*_*ett 6

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

那么,你问在使用服务之前是否应该关闭ServiceTracker:我的答案是否定的.ServiceTracker充当当前服务的"智能指针",它管理所有侦听器等,以便在服务消失时得到通知.如果您关闭了跟踪器,那么您将无法及时了解服务状态,那么您如何知道它是否仍然有效?

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

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

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

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

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

现在已经说了以上所有内容,我打算用手榴弹扔掉:请停止使用ServiceTracker!它是一个非常低级的实用程序,很少需要,然后只在"管道"或基础结构代码中.您的大多数应用程序应该使用更高级别的抽象构建.我强烈建议使用Declarative Services,这比使用ServiceTrackers更容易.


Pet*_*ens 5

服务跟踪器的最佳实践是使用声明性服务.

对于专家:有一些高度专业化的案例,其中服务跟踪器是有用的(并且是不可错过的!)但是如果你不得不问这个问题,那么服务跟踪器不适合你.服务跟踪器是一种非常低级的方式来处理中间件使用的服务,如声明式服务实现,蓝图实现等.

  • 放的好方法."如果你不得不问如何使用它,你就不应该使用它." :-) (2认同)