何时在OSGi之类的设备上使用ServiceLoader

2022-09-02 13:18:29

作为一个对依赖关系过敏的人,我什么时候会使用像OSGi这样的东西,而不是内置的java 6 http://java.sun.com/javase/6/docs/api/java/util/ServiceLoader.html(我想让插件jars被放进去)。

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


答案 1

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

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

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

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

OSGi提供了许多其他“中间件”功能。我不会试图在这里向您推销它们,因为您的问题主要集中在选择会错过的内容上。ServiceLoader


答案 2

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

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

使用ServiceLoader要记住的另一件事是尝试抽象查找机制。发布机制非常好,干净且具有声明性。但是查找(通过java.util.ServiceLoader)就像地狱一样丑陋,实现为类路径扫描程序,如果将代码放入任何没有全局可见性的环境(如OSGi或Java EE),它就会崩溃。如果你的代码纠结于此,那么你以后将很难在OSGi上运行它。最好写一个抽象,你可以在时机成熟时替换它。


推荐