2009-12-24 54 views

回答

14

如果ServiceLoader大多符合您的需求,那就表示您正在寻找通过类路径上的文件存在的服务发现。这只是OSGi提供的一小部分。

OSGi将允许您在应用程序运行时动态安装捆绑软件,广告服务,撤消广告以及卸载软件包。此外,作为服务的消费者,您可以热切地查看它们 - 通过筛选谓词查询 - 并检测提供的服务提供商何时来去。这些软件包不需要放在课程路径上,它们可以以各种形式提供; Jar文件和“爆炸目录”是我记得的两个。

相比之下,ServiceLoader只做了一件事:它揭露了可发现的工厂。通常,您将创建一个工厂样式的界面,该界面需要一些参数来决定该提供程序是否可以提供相应的服务,例如将给定的字符集名称映射到CharsetDecoder。没有正式的协议来获取和发布来自这样的提供商的服务。 OSGi确实将消费者绑定和解除绑定到服务上。当新的提供者联机时,消费者可以收到通知,并且提供者可以在消费者获取和释放服务实例时接收通知。如果这个生命周期控制对你的服务很重要,并且你放弃了OSGi,那么你必须自己来构建它; ServiceLoader不会那么远。

或者,您可以采取更加被动的声明式方法,而不是渴望的服务查找和使用方式,并让OSGi依赖管理器之一将您所声明的需求与可用服务提供者相匹配。有许多依赖管理者可供选择。 Spring Dynamic Modules是最有能力的人之一。

OSGi提供了许多其他“中间件”设施。我不会试图在这里把你卖给他们,因为你的问题主要集中在你会错过选择ServiceLoader的东西上。

+0

谢谢 - 总是很难真正知道OSGi是什么。不,我真的只需要ServiceLocator的服务,而且我很欣赏它是内置的。我只是怀疑,在我认为它一定是患病或什么之前没有听说过它。 – 2009-12-25 22:42:06

+2

我在当前项目中使用'ServiceLoader',唯一令我感到沮丧的是1)需要将扩展​​名作为Jar文件推送到类路径中(我们的应用程序不鼓励最终用户摆弄类路径) ,以及2)同一服务接口的同级提供者将被暴露给消费者的未指定顺序。后者使得很难包含“优先级”,例如用户提供的扩展应该优于应用程序的基本服务。因此,当服务提供商不会相互重叠或竞争时,最好使用ServiceLoader。 – seh 2009-12-26 14:46:37

3

正如seh指出的那样,如果您只对简单的服务发现感兴趣,那么ServiceLoader是一种轻量级的方式来将消费者与提供者分离。但它不提供任何协助组合服务。

例如,假设服务A需要使用服务B.这是一个“服务依赖”......但是如果B不可用,应该怎么办?在OSGi中,我们可以安排如果B不可用,那么A也不会 - 假设依赖是强制性的;我们也可以支持可选的依赖关系。另一方面,当使用ServiceLoader时,只要JAR将它放在类路径中,服务A就无法控制它的可用性,所以即使没有所需的“后端”服务,它也必须提供它的功能。

ServiceLoader要记住的另一件事是尝试抽象查找机制。发布机制相当不错,干净和声明。但是,查找(通过java.util.ServiceLoader)与地狱一样丑陋,实现为类路径扫描器,如果将代码放入任何不具有全局可见性的环境(例如OSGi或Java EE)中,该类扫描器可能会非常糟糕。如果你的代码纠结于此,那么你将很难在OSGi上运行它。最好写一个可以在时间到时取代的抽象。

+1

您可否详细说明ServiceLoader的简单抽象,以便稍后迁移到OSGi。我目前有一个分为12或13个jar文件的框架,它使用核心组件的serviceloader机制来为类路径上的模块“扫描”。 我希望框架能够在OSGi中很好地发挥,但不依赖于OSGi。到目前为止,我看不出如何实现二元性。使用ServiceLoader机制时,甚至有可能成为OSGi的一半和一半? – Chris 2010-07-29 07:45:38

+1

最好的抽象概念就像依赖注入一样。 在需要某些服务“Foo”的代码中,不要尝试查找该服务,而只是允许它通过setFoo()方法注入。从其他类开始,调用ServiceLoader以获取Foo的实例并将其注入需要它的代码中。 如果您以后转移到OSGi,只需取消第二个类并使用Declarative Services或Blueprint来处理注入OSGi服务。 – 2010-07-30 00:29:43

相关问题