【发布时间】:2011-02-16 02:39:26
【问题描述】:
我正在努力了解 OSGi 服务。我一直问自己的主要问题是:使用服务而不是使用捆绑包及其导出的包有什么好处?
据我所知,后期绑定的概念似乎与此有关。捆绑包依赖项在捆绑包开始时连接在一起,所以我猜它们是相当固定的。但是对于服务,它似乎几乎是一样的。捆绑包启动并注册服务或绑定到服务。当然,服务可以随时来来去去,您必须跟踪这些机会。但核心思想在我看来并没有什么不同。
另一个方面似乎是服务更加灵活。一个特定接口可能有许多实现。另一方面,对于特定的导出包,也可以有很多不同的实现。
在另一篇文章中,我读到使用导出包的缺点是它们使应用程序比服务更脆弱。作者写道,如果您从依赖图中删除一个捆绑包,将不再满足其他依赖关系,因此可能会对整个图造成多米诺骨牌效应。但是,如果服务离线,难道不会发生同样的情况吗?在我看来,服务依赖并不比捆绑依赖好。
到目前为止,我找不到一篇博文、书籍或演示文稿可以清楚地描述为什么服务比仅仅通过导出和导入包来公开功能更好。
总结一下我的问题:
使用 OSGi 服务使其优于导出和导入包的主要优势是什么?
加法
我试图收集有关此问题的更多信息,并在包和服务的普通导出/导入之间进行某种比较。也许这会帮助我们找到一个满意的答案。
-
开始/停止/更新
捆绑包(因此是包)和服务都可以启动和停止。除此之外,它们还可以进行更新。服务也与捆绑生命周期本身相关联。但在这种情况下,我的意思是您是否可以启动和停止服务或捆绑包(以便导出的包“消失”)。
-
跟踪变化
ServiceTracker 和 BundleTracker 使跟踪和响应捆绑和服务可用性的变化成为可能。
-
与其他捆绑包或服务的特定依赖关系。
如果你想使用一个导出的包,你必须导入它。
Import-Package: net.jens.helloworldnet.jens.helloworld 会提供服务吗?我还需要导入包才能获得接口。
因此,在这两种情况下,它们都会与或多或少特定的包进行某种“紧密耦合”。
-
能够拥有多个实现
特定包可以通过多个捆绑包导出。可能有一个包 net.jens.twitterclient 由包 A 和包 B 导出。这同样适用于服务。 net.jens.twitterclient.TwitterService 接口可以由包 A 和 B 发布。
在这里总结一下简短的比较(导出的包/服务):
- 是/是
- 是/是
- 是/是
- 是/是
所以没有区别。
此外,服务似乎增加了更多的复杂性并引入了另一层依赖关系(参见下面的image)。
alt text http://img688.imageshack.us/img688/4421/bundleservicecomparison.png
如果导出的包和服务之间没有真正的区别,那么使用服务有什么好处呢?
我的解释:
服务的使用似乎更复杂。但服务本身似乎更轻量级。如果您启动/停止整个捆绑包或者您只是启动和停止特定服务,这应该是不同的(在性能和资源方面)。
从架构的角度来看,我也猜想捆绑包可以被视为应用程序的基础。在启动和停止捆绑包方面,基础不应该经常改变。该功能由该包的服务在“捆绑层”之上的某种动态层中提供。这个“服务层”可能会经常发生变化。例如,如果数据库离线,查询数据库的服务将被取消注册。
你有什么看法?我是否开始了解服务的全部意义,还是我仍在思考错误的方式?有没有我遗漏的东西可以使服务比导出的包更具吸引力?
【问题讨论】:
-
偶注:在上面的3)中,如果你用接口干净地做事,你只导出包含服务接口的包。所以消费者只需要导入接口包,不需要导入实现。如果你把接口放在一个单独的包中,那么你就会得到松耦合。如果接口与 impl 在同一个包中,那么它是相当紧密的。在第 4 点),让多个包导出同一个包要求放入类加载器地狱。片段包是可能的,但你需要非常小心它们。有龙。
-
你在 3) 上是对的。我现在明白了。关于 4),导出具有相同完全限定名称的多个包没有问题。消费者包只会连接到其中一个,因此只有一组类位于消费者包的类路径上。这意味着 jar/classloader 地狱不会发生。到目前为止我还没有放弃,我在“OSGi and Equinox”一书中找到了一些东西。正如我在研究开始时所看到的那样,似乎与服务存在更多“松散耦合”。
-
你最后得出了什么结论?我问是因为我有同样的问题。我是 OSGi 的新手,并使用服务实现了一些东西。现在我想知道为什么我不简单地导出它们。
标签: service osgi late-binding