OSGI包中Bundle-Classpath的预期用例是什么?

时间:2013-06-05 07:27:15

标签: osgi osgi-bundle

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

以下是我的理解,请帮助我了解这是否正确。

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

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

3 个答案:

答案 0 :(得分:35)

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

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

  1. 只需创建我自己的代码就可以了。该bundle现在将具有声明对Guava的依赖的Import-Package语句,并且任何想要将我的bundle部署到他的应用程序中的人也必须部署Guava。

  2. 或者,我可以在我的包中包含一份Guava副本,并从我的Bundle-ClassPath引用它。部署我的软件包的人可以部署只是我的软件包,而不需要担心从哪里获取Guava。实际上,我的包中存在Guava是一个实现细节,而部署者甚至不需要知道我正在使用它。

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

    选项2的一个更严重的问题是,库的所有依赖项现在也变为 my 依赖项。实际上,Guava是一个罕见的Java库示例,它没有自己的依赖...但许多其他Java库拖入了一个巨大的传递依赖树。如果你使用这种方法,比如Hibernate,那么你自己的bundle也会有那么大的依赖集。这非常难看,非常快。

    因此,您应该谨慎,不要过度使用Bundle-ClassPath / Embed-Dependency。您应该只考虑使用它,如果依赖项是(a)小,没有传递依赖,并且(b)您的bundle使用库作为内部实现细节,即它不是您的公共API的一部分。

    <强>更新

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

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

答案 1 :(得分:3)

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

你将jar放入你的包中,

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

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

Bundle-ClassPath: foo.jar,.

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

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

答案 2 :(得分:2)

我想你可能有点不在这里。

  

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

     

这意味着当一些bundle类需要另一个类时   同一个包,包含包的整个包类路径   搜索找到班级。

来自OSGI in Action

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

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

如果您希望a.Ab.Bc.C彼此可用,则必须定义srcsrc2和{{ 1}}与bundle类路径有关。这意味着您必须在清单文件中添加以下行:

src3