我正在尝试从一些自定义OSGI平台迁移到Glassfish,以便于维护和更快地实施新捆绑包。
我在迁移时遇到了问题。所以我有BundleA和BundleB,它们应该通过服务引用进行通信。引用的接口位于BundleC上,BundleC是自定义平台上的主要捆绑包。如果没有BundleC,将无法启动,包括平台本身。所以我把接口放在BundleC上。 BundleB具有实现接口的类,并在启动时将其注册为服务,BundleA使用该服务。
在转移到Glassfish时,因为它已经提供了一个合适的OSGI平台,所以我不需要我的旧BundleC。因此,在删除BundleC之后,除了导出和导入类或包含一个用于启动的软件包之外,如何提供正确的软件包间通信?我希望BundleA和BundleB“几乎”独立,而不是耦合。
这种情况有什么解决方案吗?或者我仍然需要BundleC作为某种中间件?
答案 0 :(得分:3)
假设您有以下设置:
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(工具)中,这很简单,只需将服务包添加到Export-Package标头,然后bnd就会将包从类路径复制到包B中。确保标记要使用的包的提供复选框正确的进口版本范围。
答案 1 :(得分:1)
如果我理解你的架构,我认为你做的是正确的,除了因为你现在使用Glassfish作为你的OSGI容器,你不应该在bundle C中需要任何东西,除了你的服务接口的定义
bundle C - 应该只定义服务接口(不提供实现)。 bundle B - 实现bundle C定义的服务接口,并将自己注册为OSGI容器作为该接口的服务提供者。
bundle A - 取决于bundle C中定义的服务接口。