OSGi:Import-Package/Export-Package 和 Require-Capability/Provide 能力有什么区别?

OSGi: What's the difference between Import-Package/Export-Package and Require-Capability/Provide Capability?

我目前正在使用 OSGi 框架,但我对一些我不是 100% 清楚的概念有疑问。我自己搜索过,但我找不到一个像样的答案来清楚地解释它。

在一个包中,他的清单 header 使用的 header 中的 2 个是 Import-PackageExport-Package。名称不言自明:对特定套餐的需求和特定套餐的提供。为了获得该包(或提供该包),必须将完整的包安装在需要 Import 的框架中。

但随后我们进入了 Requirements-Capabilities 模型的部分。这实际上可以与 Import-PackageExport-Package header 相同。此 Requirements-Capability 型号也有 header:Require-CapabilityProvide-Capability。同样,这些代表要求和提供某些东西。

我知道 Requirements-Capability 模型只是后来在 OSGi 规范的开发中引入的。无法准确找到它出现的年份和版本。

但是,

当我们在 1998 年开始使用 OSGi 时,我们有一些明确的要求,但当然,并不清楚它会产生什么。所以我们开始明确地建模我们拥有的需求和能力:包。 Import-Package 需要一种能力,而这种能力是由 Export-Package 提供的。

2003 年,Eclipse 想要开始使用 OSGi,但他们需要一个工具来要求另一个包,他们不喜欢导出和导入所有包的想法。其实那个时候他们并没有看到套餐的好处。为了满足他们,我们添加了 Require-Bundle 和 Fragment-Host(他们的另一个愿望结果并不是那么好。)

在我们指定带有这些扩展的 OSGi 4.x 之后,我们开始考虑存储库,Richard 开发了 Oscar Bundle Repository。分析 OSGi 4.0 中新 headers 的情况,很明显 Import-Package 的实现看起来很像 Require-Bundle,甚至类似于 Fragment-Host 处理。

2006 年,Richard S. Hall 和我写 RFC 112 提出了一个更通用的模型,该模型捕获了现有依赖模型的语义,但并不特定于每个 类型 的要求。 IE。对于框架 解析器,Import-Package 和 Require-Bundle 仅在它们的 命名空间 上有所不同。将 Import-Package 视为通用要求,将 Export-Package 视为通用功能,这使得存储库模型变得极其简单。更好的是,它是可扩展的,因为我们总是可以添加更多的命名空间。这使得解析器完全独立于实际使用的命名空间。

经过激烈的讨论,OSGi 核心平台专家组决定接受基本思想并制定需求和能力规范。虽然这最初是存储库的模型,但事实证明它对框架本身非常有用。因此,我们决定使现有规范适应该模型。 OSGi 4.3 在内部将 Import-Package、Export-Package、Require-Bundle 等建模为 资源 (捆绑包)的要求和功能。为了向后兼容,我们保留了现有的 headers,但它们在内部转换为要求和功能。

那么终于可以回答你的问题了。随着时间的推移,OSGi 规范添加了越来越多的 命名空间 。名称空间就像是需求和能力的 type。它定义了该命名空间中 Capability 的一组属性的语义。 Requirement 是对这些属性断言的过滤器表达式。 资源 有一组能力,当其所有要求都得到满足时,这些能力会在 运行 时提供。 Resolver的任务是找到一组彼此都满意的资源集合运行time.

提供的能力和能力。

例如,我们添加了 osgi.ee 命名空间,它准确定义了捆绑包可以在哪些 VM 上运行 运行。我们添加了 osgi.extender 命名空间,它模拟对外部程序(如服务组件运行时 (SCR))的依赖。大多数 SCR 组件不需要 SCR 本身的任何包,我们努力使它们尽可能独立。但是,SCR 组件将毫无用处,除非 运行 时代的某些捆绑包提供了 SCR 功能。请注意,这不能使用 Require-Bundle,因为 SCR 有多种实现。我认为大约有 20 个名称空间。每个命名空间都在 Namespace class.

中定义

此模型为 OSGi 提供了许多优势:

  • Cohesion 尽管规范添加了许多名称空间,但解析器实现自从在通用模型上工作以来就无需更改。
  • Fine-Grained OSGi 包的独特之处在于它们以非常 fine-grained 的方式描述它们的依赖关系。我知道的所有模块系统都倾向于使用不允许替换的简单 module-to-module 依赖项。
  • 灵活 由于框架具体化了包之间的依赖关系,因此可以在 运行 时间内利用这些依赖关系。例如,在 OSGi enRoute 中,我通过这些 运行time 连接将一个包链接到它的网页。

我个人认为 OSGi 的需求和能力模型是它保守得最好的秘密之一。据我所知,它可以用于很多领域,将许多开发项目改进为软件工程领域。

这个问题唯一令人失望的部分是我认为我们在 Core specification? :-)

requirements and capabilities 模型是 Import/Export 包模型的扩展。实际上,您可以将包导入表示为需求,将包导出表示为功能。

导出/导入包允许松耦合。您导出一个 API,客户端将其导入。这样客户端只需要知道 API 就可以实现松耦合。

在稍后阶段,当您 assemble 应用程序脱离捆绑时,这种松散的耦合使得流程自动化变得困难。

如果您只是将客户端包提供给解析器,那么它只能自动找到您需要提供 API 的包。如果 API 的实现在不同的包中,那么解析器就无法知道您需要它。

这是要求可以提供帮助的地方。让我们以 HTTP Whiteboard model 为例。想要发布 servlet 的 bundle 需要导入 servlet api 包,但也需要表达它想要 osgi http 白板的实现。

这可以用namespace="osgi.implementation",name="osgi.http",version="1.1.0"的要求来表达。由于这很难手工编写,因此提供了注释支持。

@HttpWhiteboardServletPattern("/myservlet")
@Component(service = Servlet.class)
public class MyServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws IOException {
        resp.getWriter().println("Hello");
    }
}

注释@HttpWhiteboardServletPattern 间接转换为上述要求。

因此,当您使用此 class 构建捆绑包时,它将导入 servlet api 包,并且还需要一个 http 白板实现。

现在,如果您查看像 felix http 服务这样的实现包,您会发现它提供了白板实现的功能。

因此,如果您的捆绑包、servlet API 和 felix http 服务有一个 OSGi 存储库。然后解析器可以为您提供一个完整的应用程序,如果你只给它你的包。