我正在尝试了解 OSGi 服务。我一直问自己的主要问题是:使用服务而不是使用捆绑包及其导出的包有什么好处?
据我所知,似乎后期绑定(bind)的概念与它有关。捆绑依赖项在捆绑包开始时连接在一起,所以我猜它们是非常固定的。但是对于服务,它似乎几乎相同。捆绑包启动并注册服务或绑定(bind)到服务。当然,服务可以随时来来去去,您必须跟踪这些机会。但核心思想对我来说似乎没有什么不同。
另一个方面似乎是服务更加灵活。一个特定的接口(interface)可能有许多实现。另一方面,特定的导出包也可以有很多不同的实现。
在另一篇文章中,我读到使用导出包的缺点是它们使应用程序比服务更脆弱。作者写道,如果您从依赖图中删除一个包,将不再满足其他依赖关系,从而可能对整个图造成多米诺骨牌效应。但是,如果服务离线,就不会发生同样的事情吗?在我看来,服务依赖并不比捆绑依赖好。
到目前为止,我找不到一篇博文、书籍或演示文稿可以清楚地描述为什么服务比仅仅通过导出和导入包来公开功能更好。
总结一下我的问题:
使用 OSGi 服务使其优于导出和导入包的主要好处是什么?
加法
我试图收集有关此问题的更多信息,并在包和服务的普通导出/导入之间进行某种比较。也许这会帮助我们找到一个满意的答案。
捆绑包(因此是包)和服务都可以启动和停止。除此之外,它们还可以进行更新。服务也与包生命周期本身相关联。但在这种情况下,我的意思是您是否可以启动和停止服务或包(以便导出的包“消失”)。
ServiceTracker 和 BundleTracker 可以跟踪包和服务可用性的变化并使用react。
如果要使用导出的包,则必须导入它。
Import-Package: net.jens.helloworld
net.jens.helloworld 会提供服务吗?我还需要导入包才能获取接口(interface)。
因此,在这两种情况下,它们都会与或多或少特定的包有某种“紧密耦合”。
特定的包可以由多个包导出。可能有一个包 net.jens.twitterclient 由包 A 和包 B 导出。这同样适用于服务。接口(interface) net.jens.twitterclient.TwitterService 可以由包 A 和 B 发布。
在这里总结一下一个简短的比较(导出的包/服务):
所以没有区别。
此外,服务似乎增加了更多的复杂性并引入了另一层依赖关系(参见下面的 image)。
alt text http://img688.imageshack.us/img688/4421/bundleservicecomparison.png
那么,如果导出的包和服务之间没有真正的区别,那么使用服务的好处是什么?
我的解释:
服务的使用似乎更加复杂。但服务本身似乎更轻量级。如果您启动/停止整个包或者您只是启动和停止特定服务,这应该有所不同(在性能和资源方面)。
从架构的角度来看,我也猜测 bundles 可以被视为应用程序的基础。在启动和停止 bundle 方面,基础不应该经常改变。该功能由这些包的服务在“捆绑层”之上的某种动态层中提供。这个“服务层”可能会经常发生变化。例如,如果数据库离线,则用于查询数据库的服务将被取消注册。
你有什么看法?我是开始获得服务的全部意义还是我仍然在以错误的方式思考?我是否遗漏了什么会使服务比导出包裹更具吸引力?
最佳答案
它很简单:
捆绑只是提供类(class) 你可以使用。使用导入/导出,您可以屏蔽可见性并避免(例如)版本冲突。
服务是类的实例 满足某个契约(接口(interface))。
因此,在使用服务时,您不必关心实现的来源或实现细节。当您使用某项服务时,它们甚至可能会发生变化。
当您只想依赖 OSGi 的 Bundle Layer 时,您可以轻松地将横切依赖项引入到通常不需要的具体实现中。 (阅读下面关于 DI 的内容)
这不仅仅是 OSGi 的事情 - 只是很好的做法。
在非 OSGi 世界中,您可以使用依赖注入(inject) (DI) 框架,如 Guice、Spring 或类似的。 OSGi 将服务层内置到框架中,并让更高级别的框架(Spring、Guice)使用该层。 - 所以最后你通常不直接使用 OSGi 服务 API,而是使用来自用户友好框架(Spring-->Spring DM、Guice-->Peaberry 等)的 DI 适配器。
哈,
托尼
关于service - 为什么我应该更喜欢 OSGi 服务而不是导出的包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2776384/