【问题标题】:Why should I prefer OSGi Services over exported packages?为什么我应该更喜欢 OSGi 服务而不是导出的包?
【发布时间】:2011-02-16 02:39:26
【问题描述】:

我正在努力了解 OSGi 服务。我一直问自己的主要问题是:使用服务而不是使用捆绑包及其导出的包有什么好处?

据我所知,后期绑定的概念似乎与此有关。捆绑包依赖项在捆绑包开始时连接在一起,所以我猜它们是相当固定的。但是对于服务,它似乎几乎是一样的。捆绑包启动并注册服务或绑定到服务。当然,服务可以随时来来去去,您必须跟踪这些机会。但核心思想在我看来并没有什么不同。

另一个方面似乎是服务更加灵活。一个特定接口可能有许多实现。另一方面,对于特定的导出包,也可以有很多不同的实现。

在另一篇文章中,我读到使用导出包的缺点是它们使应用程序比服务更脆弱。作者写道,如果您从依赖图中删除一个捆绑包,将不再满足其他依赖关系,因此可能会对整个图造成多米诺骨牌效应。但是,如果服务离线,难道不会发生同样的情况吗?在我看来,服务依赖并不比捆绑依赖好。

到目前为止,我找不到一篇博文、书籍或演示文稿可以清楚地描述为什么服务比仅仅通过导出和导入包来公开功能更好。

总结一下我的问题:

使用 OSGi 服务使其优于导出和导入包的主要优势是什么?


加法

我试图收集有关此问题的更多信息,并在包和服务的普通导出/导入之间进行某种比较。也许这会帮助我们找到一个满意的答案。

  1. 开始/停止/更新

    捆绑包(因此是包)和服务都可以启动和停止。除此之外,它们还可以进行更新。服务也与捆绑生命周期本身相关联。但在这种情况下,我的意思是您是否可以启动和停止服务或捆绑包(以便导出的包“消失”)。

  2. 跟踪变化

    ServiceTracker 和 BundleTracker 使跟踪和响应捆绑和服务可用性的变化成为可能。

  3. 与其他捆绑包或服务的特定依赖关系。

    如果你想使用一个导出的包,你必须导入它。

    Import-Package: net.jens.helloworld
    

    net.jens.helloworld 会提供服务吗?我还需要导入包才能获得接口。

    因此,在这两种情况下,它们都会与或多或少特定的包进行某种“紧密耦合”。

  4. 能够拥有多个实现

    特定包可以通过多个捆绑包导出。可能有一个包 net.jens.twitterclient 由包 A 和包 B 导出。这同样适用于服务。 net.jens.twitterclient.TwitterService 接口可以由包 A 和 B 发布。

在这里总结一下简短的比较(导出的包/服务):

  1. 是/是
  2. 是/是
  3. 是/是
  4. 是/是

所以没有区别。

此外,服务似乎增加了更多的复杂性并引入了另一层依赖关系(参见下面的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


【解决方案1】:

很简单: 捆绑包只是提供您可以使用的。使用 Imports/Exports,您可以屏蔽可见性并避免(例如)版本控制冲突。 服务是满足特定契约(接口)的类的实例

因此,在使用服务时,您不必关心实现的来源或实现细节。它们甚至可能在您使用某项服务时发生变化。

当您只想依赖 OSGi 的捆绑层时,您可以轻松地将横切依赖项引入您通常不想要的具体实现。 (阅读下面关于 DI 的内容)

这不仅仅是 OSGi 的事情 - 只是一种好的做法。

在非 OSGi 世界中,您可以使用 Guice、Spring 或类似的依赖注入 (DI) 框架。 OSGi 在框架中内置了服务层,并允许更高级别的框架(Spring、Guice)使用该层。 - 所以最后你通常不直接使用 OSGi 服务 API,而是使用用户友好框架(Spring-->Spring DM、Guice-->Peaberry 等)的 DI 适配器。

HTH, 托尼

【讨论】:

    【解决方案2】:

    我建议购买这本书。它在解释服务和构建使用 OSGi 服务的重要应用程序方面做得非常出色。

    http://equinoxosgi.org/

    我的公司经常使用服务构建 100 多个捆绑应用程序。我们从使用服务中获得的主要好处是:

    1) 生产者/消费者实现的松散耦合

    2) 热插拔服务提供商

    3) 更简洁的应用架构

    【讨论】:

    • 我对服务进行了更多调查。在我看来,从技术角度来看,您可以通过导出/导入实现与服务一样多的动态性。但!我开始认为服务是更好的选择,因为 a) 它们更易于管理,b) 更轻量级。你有什么意见?由于您的公司似乎在做一些严肃的 OSGi 工作,您是否认为具有动态服务的捆绑包的相对固定基础比启动和停止捆绑包(如服务)并使用 BundleTracker 跟踪它们更好?
    • 请随时给我发送电子邮件,因为评论框空间不足。我的公司采用了以下最佳实践: 捆绑仅导出包含 Java 接口的包。 (这确保没有实现绑定)所有 Java 代码都没有对 OSGi 定义的类的引用。 (我们使用 POJO 进行所有应用程序设计 - 普通旧 Java 对象)使用声明式服务发布和注入服务。 (简单的 XML 文件和清单中的 1 行;加上它的工具在 Eclipse 3.5 及更高版本中非常棒)空间不足,如果需要更多详细信息,请联系我。
    【解决方案3】:

    当您从 OSGi 开始时,从导出包方法开始总是更容易,它确实感觉更像 java。但是,当您的应用程序开始增长并且您需要一点动态性时,服务就是要走的路。

    Export-package 仅在启动时进行解析,而 services 是持续的解析(您可能想要或不想要)。从支持的角度来看,拥有服务可能非常可怕(它是确定性的吗?如何复制问题?),但它也非常强大。

    Peter Kriens 解释了为什么他认为服务是一种范式转变,就像当时的 OO 一样。见µServicesDuct Tape

    在我所有的 OSGi 经验中,我还没有机会实现复杂的服务(即超过一层),当然注释似乎是要走的路。您还可以使用Spring dynamic module 来减轻与服务跟踪器打交道的痛苦。 (以及许多其他选项,例如 iPOJOBlueprint

    【讨论】:

      【解决方案4】:

      让我们考虑以下两种情况:

      1. Bundle A 提供了一个算术加法服务add(x,y) return x+y。为此,它使用“IAddition 接口”导出“mathOpe 包”,并在服务注册表中注册服务。 Bundle B、C、D、...使用此服务。

      2. Bundle A 导出“mathOpe 包”,我们在其中发现了一个类 Addition,它公开了一个操作 (x+y)<--add(x,y)。 Bundles B、C、D、...导入包 mathOpe。

      方案 1 与方案 2 的比较:

      • 只有一个实现实例与多个实例(随意将其设为静态!)
      • 动态服务管理启动、停止、更新与无管理,消费者拥有实施(“服务”)
      • 灵活(我们可以想象通过网络提供远程服务)与不灵活

      ...等等。

      PS:我不是 OSGI 专家,也不是 Java 专家,这个答案仅表明我对这些现象的理解 :)

      【讨论】:

        【解决方案5】:

        我认为这篇优秀的文章可以回答你的很多问题:OSGi, and How It Got That Way

        【讨论】:

        • 我已经阅读了这篇文章。 Neil 在解释 OSGi 方面做得很好。在过去的几周里,我看到了他的很多作品。但即使是他也没有真正说明为什么服务是更好的选择。也许一个长期的 Java 程序员会立即看到好处。但是我对 Java 比较陌生,所以我需要一点额外的解释;)
        【解决方案6】:

        使用服务而不是实现类的主要优点是提供服务的包将执行类本身的初始化。

        使用服务的包不需要知道服务是如何初始化的。

        如果您不使用服务,您将始终需要调用一种工厂来创建服务实例。该工厂将泄露应保密的服务细节。

        【讨论】:

          猜你喜欢
          • 2011-04-01
          • 2017-01-01
          • 2022-01-08
          • 1970-01-01
          • 1970-01-01
          • 2011-05-10
          • 2013-12-01
          • 2017-12-21
          • 2013-04-30
          相关资源
          最近更新 更多