何时使用ServiceLoader而不是OSGi之类的东西

时间:2009-12-24 22:53:27

标签: java osgi serviceloader

作为对依赖性过敏的人,我什么时候会使用像OSGi这样的内容而不是内置的java 6 http://java.sun.com/javase/6/docs/api/java/util/ServiceLoader.html(我想让插件罐子掉进去)。

(仅供参考,这是在scala应用程序中,对任何建议开放,ServiceLoader非常接近我想要的)。

2 个答案:

答案 0 :(得分:16)

如果ServiceLoader最符合您的需求,则说您正在通过类路径上的文件存在来寻找服务发现。这只是OSGi提供的一小部分。

OSGi将允许您在应用程序运行时动态安装捆绑包,宣传服务,撤消广告和卸载捆绑包。此外,作为服务的消费者,您可以热切地查找它们 - 使用过滤谓词查询 - 并检测提供的服务提供商何时来去。这些束不必位于类路径上,它们可以以各种形式提供;我回忆起Jar文件和“爆炸目录”。

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

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

OSGi提供了许多其他“中间件”设施。我不打算在这里向你推销,因为你的问题主要集中在选择ServiceLoader时你会错过的内容。

答案 1 :(得分:4)

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

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

ServiceLoader要记住的另一件事是尝试抽象查找机制。发布机制非常好,干净,声明性强。但是查找(通过java.util.ServiceLoader)和地狱一样难看,实现为类路径扫描程序,如果将代码放入没有全局可见性的任何环境(例如OSGi或Java EE)中,则会严重破坏。如果您的代码与之纠缠在一起,那么您将很难在OSGi上运行它。最好写一个可以在时机成熟时替换的抽象。