【问题标题】:OSGI Inter-bundle Communication on GlassfishGlassfish 上的 OSGI 包间通信
【发布时间】:2013-08-07 06:00:06
【问题描述】:

我正在尝试从一些自定义 OSGI 平台迁移到 Glassfish,以便于维护并更快地实施新的捆绑包。

我在迁移时遇到了一个问题。所以我有 BundleA 和 BundleB,它们应该通过服务引用进行通信。参考的接口在 BundleC 上,它是自定义平台上的主要包。如果没有 BundleC,什么都不会启动,包括平台本身。所以我把接口放在了BundleC上。 BundleB 具有实现接口的类,并在启动时将其注册为服务,而 BundleA 使用该服务。

在迁移到 Glassfish 时,由于它已经提供了合适的 OSGI 平台,我不需要旧的 BundleC。那么在删除 BundleC 之后,除了导出和导入类或包含一个用于启动的包之外,如何提供适当的包间通信?我希望 BundleA 和 BundleB “几乎”独立,而不是耦合。

这种情况有什么解决办法吗?或者我仍然需要那个 BundleC 作为某种中间件?

【问题讨论】:

    标签: java glassfish osgi


    【解决方案1】:

    假设您有以下设置:

                         Service    
      +-------+                                +-------+
      |   A   |---get------|>---register-------|   B   |
      +-------+             .                  +-------+
          !                 .                     !
          !         [service package]             !
          !                 .                     !
          !             +-------+                 !
          \----import-->|   C   |<---import-------/
                        +-------+
    

    这意味着有 2 个生命周期。首先 A 和 B 必须针对 C 进行解析。C 的目的是使 A 和 B 彼此分离,因为它包含唯一的共享部分,即接口。所以从纯粹的耦合问题来看,这总体上还不错,很多人都推荐它。

    然而,这个模型的问题是你会得到很多只包含接口的小包(虽然称它为中间件似乎有点牵强)。

    因此,我通常选择其中一个捆绑包并将其导出服务包。选择的捆绑包必须是服务的提供者。这通常是您的服务接口的实现者(但不一定是,请阅读OSGi Semantic Versioning Whitepaper 了解详细信息)。提供者是履行服务接口包所定义的服务契约的捆绑包。服务的提供者很可能是 B 包。

    Bundle B 然后会导出服务接口的包。 Bundle A 导入这个包。这提供了一个非常好的依赖模型:Bundle A 依赖于服务接口的包,但不依赖于 Bundle B。接口包的任何其他提供者都可以正常工作。同时,在至少有一个提供程序导出包之前,包 A 不会启动。所以你有一个非常好的依赖管理解决方案,只需要 2 个包而不是 3 个。

      +-------+                                +-------+
      |   A   |---get------|>---register-------|   B   |
      +-------+             .                  +-------+
          !                 .                     ^
          !         [service package]             !
          !                 .                     !
          \----import-----------------------------/
    

    在 bnd(tools) 中,这很简单,只需将服务包添加到您的 Export-Package 标头,然后 bnd 会将包从类路径复制到包 B。确保您标记要使用的包的提供复选框导入的正确版本范围。

    【讨论】:

    • 虽然你的解释很详细,但如果它做了我试图避免的事情,我会感到困惑。因此,如果将接口及其实现放在包 A 中,然后注册它,从包 B 调用它,我需要导入它,这使得包耦合。还是我错过了什么?
    【解决方案2】:

    如果我正确理解您的架构,我认为您做的是正确的事情,除了因为您现在使用 Glassfish 作为您的 OSGI 容器,您应该不需要 bundle C 中的任何东西,除了您的服务接口的定义.

    bundle C - 应该只定义服务接口(不提供实现)。 bundle B - 实现了 bundle C 定义的服务接口,并将自己注册到 OSGI 容器作为该接口的服务提供者。

    bundle A - 依赖于 bundle C 中定义的服务接口。

    【讨论】:

    • 有没有办法摆脱那个捆绑包C?我的意思是除了这个实现之外还有其他的吗?
    • 当然,如果你愿意,你可以去掉 bundle C。您需要在包 B 中定义接口。由于 B 会定义它并实现它,您就可以摆脱 C。但是如果您希望该接口有多个实现(或版本),那么它会使将接口的定义留在 C 中是有意义的。这种模式有助于模块化并保持你的包依赖关系图干净。
    • 感谢您的 cmets 和回答,我决定在 glassfish 上使用 jms,这将删除第三个捆绑包以及两个捆绑包之间的耦合 :)
    猜你喜欢
    • 2015-01-14
    • 2016-11-30
    • 2017-02-06
    • 1970-01-01
    • 2017-08-29
    • 2012-03-27
    • 2012-10-10
    • 2012-04-03
    • 2011-03-09
    相关资源
    最近更新 更多