何时使用ServiceLoader而不是像OSGi这样的东西

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

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

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

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

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

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

OSGi提供了许多其他“中间件”设施。 我不会试图在这里推销你,因为你的问题主要集中在选择ServiceLoader你会错过什么。

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

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

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