OSGI 包中 Bundle-Classpath 的预期用例是啥

Posted

技术标签:

【中文标题】OSGI 包中 Bundle-Classpath 的预期用例是啥【英文标题】:What is the intended use case for Bundle-Classpath in OSGI bundlesOSGI 包中 Bundle-Classpath 的预期用例是什么 【发布时间】:2013-05-31 19:10:46 【问题描述】:

我正在尝试了解 OSGI 包中 Bundle-Classpath 的预期用例。

这是我的理解,如果正确,请帮助我理解。

假设我正在创建一个 OSGI 包,该包将部署在其他包的生态系统中。我正在处理的捆绑包需要一些其他捆绑包,但它们没有在这个生态系统中加载/导出,我无法控制生态系统导出的内容。在这种情况下,我可以将这些包放在某个目录(比如“lib”)中,该目录将成为我的包的一部分。这些包也应该从 Bundle-Classpath 中引用,以便可以加载它们。

这是 Bundle-Classpath 的正确用例吗? 这些额外的包是否也会加载到 OSGI 容器中,并且由它们导出的包是否可用于其他包?

【问题讨论】:

【参考方案1】:

Bundle-ClassPath 旨在将依赖项包含在我们的包中,以便我们的包可以独立部署。

让我们举个例子。假设我的包中的代码使用了一个库,例如谷歌番石榴。我有两种打包打包方式的选择:

    只需创建我的包,其中只有我自己的代码。该包现在将具有声明对 Guava 的依赖关系的 Import-Package 语句,任何想要将我的包部署到他的应用程序中的人也必须部署 Guava。

    或者,我可以在我的包中包含 Guava 的副本,并从我的 Bundle-ClassPath 中引用它。部署我的包的任何人都可以部署我的包,而无需担心从哪里获取 Guava。事实上,我的 bundle 中 Guava 的存在只是一个实现细节,部署者甚至不需要知道我在使用它。

这两个选项之间的选择是一种权衡。选项 2 的优点是我的包更容易部署,因为它是独立的——它需要的一切都在其中。另一方面,我的包比它需要的要大得多,如果许多其他包也嵌入了他们自己的 Guava 副本,这可能会成为一个问题。

选项 2 的一个更严重的问题是库的所有依赖项现在也都变成了 my 依赖项。实际上,Guava 是一个罕见的没有自身依赖的 Java 库示例……但许多其他 Java 库拖入了一个巨大的传递依赖树。如果您将这种方法与 Hibernate 一起使用,那么您自己的 bundle 也将具有那么大的依赖集。这变得非常丑陋,非常快。

所以,你应该小心不要过度使用Bundle-ClassPath/Embed-Dependency。仅当依赖项 (a) 很小且没有传递依赖项,并且 (b) 您的包使用该库作为内部实现细节时,您才应该考虑使用它,即它不是您的公共 API 的一部分。

更新

我忘了回答你关于出口的第二个问题。答案是否定的,你放在Bundle-ClassPath 上的任何“包”的导出都不会成为你自己包的导出。事实上,我们放在Bundle-ClassPath 上的 JAR 根本不被视为捆绑包,它们只是 JAR。

您可以选择导出来自 Bundle-ClassPath 上 JAR 中的包,但您必须在自己的包的 MANIFEST.MF 中执行此操作。

【讨论】:

非常感谢!只是我正在寻找的解释:-) 谢谢!写的很棒。我想推荐一篇中等文章。 :) 谢谢,在被困在一个问题上几个小时后,这救了我!【参考方案2】:

此标头最常见的用例是外部库的打包。假设您有一些库 foo.jar,并希望在您的包中使用它的类。

你像这样把罐子放进你的包里,

/
  com/company/Activator.class
  foo.jar
  META-INF/MANIFEST.MF

在你的清单中,你现在可以使用

Bundle-ClassPath: foo.jar,.

记得在类路径中包含.,否则您将无法在包中找到这些类。

当类在Bundle-ClassPath 上时,您可以像使用任何其他类一样使用它们:在您的代码中使用它们,或导出它们。

【讨论】:

当我将一个 jar(非 osgi)放在 Bundle-Classpath 上时,我是否必须将它导入的类包含到我的 Import-Package 语句中? 否:这些类的处理方式与您的包中的任何其他类完全相同。 谢谢,那我想一定是 Maven 捆绑插件迫使我导入 jar 使用的类 嗯,不确定。尝试使用生成的包的实际布局、清单和您使用的 Maven 语句来更新您的问题。 看起来 Maven Bundle 插件确实需要导入 jar 中的类,即使它不是 OSGI jar。我将深入挖掘并更新我的问题......谢谢!【参考方案3】:

我觉得你可能有点离题了。

Bundle-Classpath 是一个有序的、以逗号分隔的相对列表 要搜索类和资源的捆绑 JAR 文件位置 请求。

这意味着当某个包类需要另一个类时 同一个包,包含包的整个包类路径 被搜索以找到类。

来自OSGI in Action。

让我们考虑一个具体的案例。想象一个具有以下结构的包(JAR 文件):

src/a/A.class
src2/b/B.class
src3/c/C.class

如果您希望a.Ab.Bc.C 可供彼此使用,则必须将srcsrc2src3 定义为与捆绑类路径有关。这意味着您必须在清单文件中添加以下行:

Bundle-ClassPath: src,src2,src3

【讨论】:

以上是关于OSGI 包中 Bundle-Classpath 的预期用例是啥的主要内容,如果未能解决你的问题,请参考以下文章

osgi笔记

OSGi 包中的 Websphere 8.5 + CXF。是不是可以?

如何使用 Maven 将第 3 方 OSGi 捆绑包添加到部署包中?

OSGi:导出一个包而不导出同一个包中的几个类

如何将特定的 java 模块嵌入到 OSGi 包中?甚至可能吗?

使用从 OSGi 包中的库为 Kura 创建的现有插件项目