我目前正在使用OSGi框架,但是我对一些并非100%清晰的概念有疑问。我自己在搜索它,但找不到清晰的解释清楚的答案。
在捆绑包中,他使用的标头的清单标头2是Import-Package
和Export-Package
。名称不言自明:对特定包装的需求和特定包装的供应。为了获得该软件包(或提供该软件包),必须将完整的软件包安装在需要 Import 的框架中。
但是接下来我们进入Requirements-Capabilities
模型的一部分。实际上,这可以与Import-Package
和Export-Package
标头相同。此Requirements-Capability
模型也有标头:Require-Capability
和Provide-Capability
。同样,这些代表要求和提供东西。
我知道Requirements-Capability
模型只是在后来的OSGi规范的开发中引入的。找不到确切的年份和版本。
但是
为什么要将此添加到规范中?我没有看到它比已经提供的Import
/ Export-package
所能提供的更多:创建对其他软件包/捆绑包的依赖关系?
有人可以让我更好地理解这两组概念之间的区别(赞成与反对)吗?
答案 0 :(得分:17)
当我们在1998年开始使用OSGi时,我们有一些明确的要求,但是当然,对于由此产生的结果尚无明确的看法。因此,我们开始显式地对我们的需求和功能进行建模:程序包。导入包需要一种功能,而该功能由导出包提供。
2003年,Eclipse希望开始使用OSGi,但他们需要一种工具来需要另一个捆绑软件,他们不喜欢导出和导入所有软件包的想法。实际上,那时他们没有看到软件包的好处。为了满足他们的需求,我们添加了Require-Bundle和Fragment-Host(他们的另一种愿望却表现得不太好。)
在使用这些扩展名指定了OSGi 4.x之后,我们开始考虑存储库,Richard开发了Oscar Bundle存储库。通过使用OSGi 4.0中的新头分析情况,可以清楚地看到Import-Package的实现与Require-Bundle非常相似,甚至类似于Fragment-Host处理。
2006年,Richard S. Hall和我写了RFC 112,提出了一个更通用的模型,该模型捕获了现有依赖模型的语义,但并不针对每种需求类型。即对于框架 resolver ,Import-Package和Require-Bundle的区别仅在于它们的 namespace 。将Import-Package视为通用需求,而将Export-Package视为通用功能使存储库模型极其简单。更好的是,它是可扩展的,因为我们总是可以添加更多的命名空间。这使得解析器完全独立于所使用的实际名称空间。
在进行了非常激烈的讨论之后,OSGi核心平台专家组决定接受基本思想并制定了“需求和功能”规范。尽管这最初是存储库的模型,但事实证明它对框架本身非常有用。因此,我们决定使现有规格适应该模型。 OSGi 4.3在内部将Import-Package,Export-Package,Require-Bundle等建模为资源(捆绑软件)的需求和功能。为了向后兼容,我们保留了现有的标头,但在内部将它们转换为需求和功能。
然后终于回答了您的问题。随着时间的流逝,OSGi规范添加了越来越多的命名空间。命名空间就像 type 一样,代表了需求和能力。它定义了该命名空间中功能的一组属性的语义。 Requirement是在这些属性上声明的过滤器表达式。 资源具有一组功能,当满足其所有要求时,这些功能将提供给运行时。 解析器的任务是找到一组对彼此的功能和运行时提供的功能都满意的资源。
例如,我们添加了osgi.ee
名称空间,该名称空间准确定义了捆绑软件可以在哪些VM上运行。我们添加了osgi.extender
名称空间,该名称空间对外部程序(如服务组件运行时(SCR))的依赖关系进行建模。大多数SCR组件不需要SCR本身的任何包装,我们努力使它们尽可能独立。但是,除非运行时中的某些捆绑包提供SCR功能,否则SCR组件将毫无用处。注意,这不能使用Require-Bundle,因为SCR有多种实现。我认为大约有20个名称空间。每个命名空间都在Namespace
类中定义。
此模型为OSGi提供了许多优点:
我个人认为OSGi的“需求和能力”模型是其最佳机密之一。据我所知,它可以用于许多领域,以将许多开发项目改进到软件工程领域。
这个问题中唯一令人失望的部分是我认为我们在Core specification中描述得非常好吗? :-)
答案 1 :(得分:6)
requirements and capabilities模型是“导入/导出”包模型的扩展。实际上,您可以将软件包导入表示为需求,而将软件包导出表示为功能。
导出/导入包允许松散耦合。您导出一个API,然后客户端将其导入。这样,客户端只需要了解API即可实现松散耦合。
在以后的阶段中,当您将应用程序捆绑在一起打包时,这种松散的耦合使自动化过程变得困难。
如果仅将客户端捆绑软件提供给解析器,则它只能自动发现您需要提供API的捆绑软件。如果该API的实现位于其他捆绑软件中,则解析器无法知道您是否需要它。
这是需求可以提供帮助的地方。让我们以HTTP Whiteboard model为例。想要发布servlet的包需要导入servlet api包,但是还需要表达它想要osgi http白板的实现。
这可以通过名称空间=“ osgi.implementation”,名称=“ osgi.http”,版本=“ 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批注间接转换为上述要求。
因此,当您使用此类构建捆绑包时,它将导入servlet api程序包,并且还要求使用http白板实现。
现在,如果您查看像felix http服务这样的实现捆绑包,您会发现它提供了针对白板展示的功能。
因此,如果您的软件包具有OSGi存储库,Servlet API和felix http服务。然后,仅将捆绑软件提供给您,解析器即可为您提供完整的应用程序。