【问题标题】:Per-Context services in OSGiOSGi 中的按上下文服务
【发布时间】:2012-10-08 10:51:15
【问题描述】:

我正在设计一个应用程序,它的功能需要在不同的上下文中保持相同。参考下图:

+----+ +----+ +----+ |B1 +--->-----+B2 +-->----+B3 | |ctx1|使用 |ctx1|使用 |ctx1| +----+服务+----+服务+----+ +-------+ +----+ +----+ +----+ |上下文| |B1 +--->-----+B2 +-->----+B3 | |经理| |ctx2|使用 |ctx2|使用 |ctx2| | | +----+服务+----+服务+----+ | | : : : +-------+ : : : +----+ +----+ +----+ |B1 +--->-----+B2 +-->----+B3 | |ctxN|使用 |ctxN|使用 |ctxN| +----+服务+----+服务+----+

有 4 个捆绑包:

  • 上下文管理器
  • B1
  • B2
  • B3

Context Manager 是负责了解新上下文何时可用并实例化 B1B2 的新版本的包> 和 B3B2B3 提供的服务在上下文中完全相同,只是我想在服务上添加一个属性以区分它在哪个上下文中运行(ctx1 vs ctxN for例子)。 现在这是我想要实现的理论,我认为我可以通过声明式服务轻松实现它,实际上我制作了 B1 *B2* 和 B3 ComponentFactory 通过在组件头中指定 component.factory 属性,我设置 B1 引用 B2 提供的服务strong>,我还设置了 B2 来引用 B3 提供的服务。 这些是我面临的挑战:

  • Context Manager第一次了解到B3提供的ComponentFactory服务,只要B1和B2 还不满意,他们没有在服务注册表中注册 ComponentFactory 服务。只要是这种情况,B1B2 就不会为第一个上下文实例化。
  • B1B2 一旦创建,从其他上下文获取任意服务,我正在考虑将 reference.target 参数设置为仅从同一上下文中选择服务,但它没有'似乎没有任何方法可以声明这样做,似乎从同一上下文中选择服务的唯一方法是通过设置基数 0..n 的引用并提供 “bind” 方法基于当前上下文进行选择,这意味着每个组件都必须复制相同的选择逻辑,而我认为可以由 上下文管理器 提供 newInstance叫做。事实上,如果在调用期间 ComponentFactory.newtInstance(props); 我可以提供像 .target=(context=mycontext) 这样的属性,那么这可以实现,但我不知道所有的参考组件实际上正在使用。

此时我正在考虑实际上避免使用声明式服务并让每个上下文包扩展一个我将提供的基类,该基类将基本上实现类似于 org.apache.felicy.dependencymanager 的依赖项跟踪,但这样每个上下文组件的开发人员不必担心知道代码位于哪个上下文中。但是我不想恢复到这个解决方案,我觉得我只是在复制逻辑可能已经存在于 OSGi 规范中,所以我的问题是:

在 OSGi 中创建可以在每个上下文基础上运行的包的最佳方法是什么,这样包可以以声明性方式描述依赖关系,而不必明确提及它们所在的上下文跑了吗?

【问题讨论】:

  • 使用声明式服务应该没有问题。由于属性传播,您可以从配置中设置像target 这样的属性。
  • 是的,可以提前知道我可以设置目标的参考,但这里的问题有两个:1)我需要首先发现工厂组件来实例化 2)我需要在组件中发现对服务的实例化引用。如果我解决了前两个问题,我可以从配置中设置目标属性。但我无法达到这一点。

标签: osgi declarative-services


【解决方案1】:

这里有一些令人困惑的术语。您谈到捆绑 B1、B2 和 B3。您还谈到了实例化 B1、B2 和 B3 的新版本。您的意思是更新捆绑包 B1、B2 和 B3?还是说捆绑包 B1、B2 和 B3 分别提供服务 S1、S2 和 S3?

【讨论】:

  • BJ,让我澄清一下,B1 B2 和 B3 是捆绑包,它们中的每一个都声明了一个服务组件(如声明式服务规范所定义)。 3个包中的每个服务组件都标记为组件工厂,因此B1,B2和B3实际上在多个实例中实例化,如图中我提到的:B1 ctx1,B2 ctx1,B3 ctx1,.., B1 ctxN,B2 ctxN,B3 ctxN。 B1 的每个实例都使用由 B2 的实例提供的服务(我们称之为 S2,但图中没有报告)。 B2 与 B3 的情况类似。
  • 所以 B1 是一个包含 DS 组件 C1 的包。 C1 是一个组件工厂,因此可以有许多 C1 实例注册为服务 S1。 B2/C2/S2 和 B3/C3/S3 相同。因此,您想使用 C3 的 ComponentFactory 来创建 C3 的实例,注册 S3 满足 C2 从而注册 C2 的 ComponentFactory,然后您使用它来创建 C2 的实例,该实例使用 S3 并注册 S2,然后满足 C1 从而注册 ComponentFactory对于 C1,然后您使用它来创建使用 S2 并注册 S1 的 C1 实例?
  • 是的,但我想在依赖关系得到满足之前了解 C1/C2/C3 工厂,否则出现第一个问题。正如我所说,DS 似乎不允许你这样做,所以我也在寻找 DS 以外的替代方案,但我不想恢复到手动跟踪依赖项。
【解决方案2】:

回答我自己的问题。只要我需要解决方案,在 Apache Felix DependencyManager 的帮助下,我已经替换了声明式服务,并且对于每个上下文,捆绑(下面源代码中的容器)我创建了一个新的依赖管理器实例有助于在每个上下文基础上跟踪服务。

有关代码参考,请查看: OpenDayLight ComponentActivatorAbstractBase

为了管理依赖并确保它们在同一个上下文中,创建了一个特殊的 ServiceDependency,供参考:OpenDayLight ServiceDependency

例如激活器的实际使用方法参考:OpenDayLight sample activator

希望这对其他人也有用。

【讨论】:

    猜你喜欢
    • 2018-07-11
    • 1970-01-01
    • 2011-11-01
    • 2012-06-24
    • 2013-06-14
    • 2019-07-23
    • 2014-05-15
    • 1970-01-01
    • 2015-07-20
    相关资源
    最近更新 更多