假设您有以下设置:
Service
+-------+ +-------+
| A |---get------|>---register-------| B |
+-------+ . +-------+
! . !
! [service package] !
! . !
! +-------+ !
\----import-->| C |<---import-------/
+-------+
这意味着有 2 个生命周期。首先 A 和 B 必须针对 C 进行解析。C 的目的是使 A 和 B 彼此分离,因为它包含唯一的共享部分,即接口。因此,从纯粹的耦合问题来看,这总体上还不错,很多人都推荐它。
然而,这个模型的问题是你会得到很多只包含接口的小包(尽管称它为中间件似乎有点牵强)。
因此,我一般选择其中一个捆绑包并将其导出服务包。选择的捆绑包必须是服务的提供者。这通常是您的服务接口的实现者(但不一定是,请阅读OSGi 语义版本控制白皮书了解详细信息)。提供者是履行服务接口包所定义的服务契约的捆绑包。服务的提供者可能是捆绑包 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 中。确保标记包的提供复选框以使用正确的版本进口范围。