1998年,我们开始使用OSGi,有一些明确的要求,但当然没有清晰的预见。因此,我们开始明确地对我们拥有的要求和能力进行建模:包。Import-Package需要一种能力,而这种能力是由Export-Package提供的。
2003年,Eclipse想要开始使用OSGi,但他们需要一个工具来要求另一个bundle,他们不喜欢导出和导入所有的包的想法。实际上,在那个时候,他们未能看到包的好处。为了满足他们,我们添加了Require-Bundle和Fragment-Host(他们的另一个愿望,结果并不是很好)。
在我们指定了带有这些扩展的OSGi 4.x之后,我们开始思考一个存储库,Richard开发了Oscar Bundle Repository。分析OSGi 4.0中新标头的情况,Import-Package的实现看起来很像Require-Bundle,甚至类似于Fragment-Host处理。
2006年,Richard S. Hall和我撰写了
RFC 112,提出了一个更通用的模型,捕捉现有依赖模型的语义,但不针对每种需求进行特定的处理。也就是说,对于Framework解析器,Import-Package和Require-Bundle仅在其命名空间上有所不同。将Import-Package视为通用需求,将Export-Package视为通用能力,使存储库模型变得极为简单。更好的是,它是可扩展的,因为我们始终可以添加更多的命名空间。这使得解析器完全独立于实际使用的命名空间。
经过一番激烈的讨论,OSGi核心平台专家组决定接受基本想法并制定了需求和能力规范。虽然这最初是用于存储库的模型,但事实证明它对框架本身非常有用。因此,我们决定将现有规范适应于此模型。OSGi 4.3在内部将Import-Package、Export-Package、Require-Bundle等视为资源(bundle)的要求和能力。为了向后兼容,我们保留了现有头文件,但它们在内部被转换为要求和能力。
然后最终回答您的问题。随着时间的推移,OSGi规范添加了越来越多的命名空间。命名空间类似于要求和能力的类型。它定义了该命名空间中一组能力属性的语义。要求是对这些属性断言的过滤器表达式。资源具有一组能力,当它的所有要求都得到满足时,这些能力提供给运行时。解析器的任务是找到一组资源,这些资源都互相满足,并满足运行时提供的能力。
例如,我们添加了
osgi.ee
命名空间来精确定义bundle可以在哪些VM上运行。我们添加了
osgi.extender
命名空间来模拟对外部程序(如服务组件运行时(SCR))的依赖关系。大多数SCR组件不需要来自SCR本身的任何包,我们努力使它们尽可能独立。但是,除非运行时中的某个bundle提供SCR功能,否则SCR组件将无用。请注意,这不能使用Require-Bundle,因为SCR有多个实现。我认为有大约20个命名空间。每个命名空间都在一个
Namespace
类中定义。
这个模型给OSGi带来了许多优势:
-
内聚性 虽然规范添加了许多命名空间,但解析器实现从未改变,因为它们适用于通用模型。
-
细粒度 OSGi bundles在描述它们的依赖关系方面是独特的,以非常细粒度的方式进行描述。我所知道的所有模块系统都倾向于使用简单的模块到模块的依赖关系,而这种依赖关系不允许替换。
-
灵活性 由于框架将bundles之间的依赖关系具体化,因此在运行时可以利用这些依赖关系。例如,在OSGi enRoute中,我通过遍历这些运行时连线将bundle链接到其网页。
我个人认为,OSGi的要求和能力模型是它最好保守的秘密之一。就我所见,它可以在许多领域中使用,以将许多开发项目改进为软件工程领域的一部分。
这个问题唯一令人失望的部分是我认为我们在
核心规范中已经相当好地描述了这一点。 :-)