Osgi 从实现包导出API

Osgi 从实现包导出API,osgi,bnd,Osgi,Bnd,有人能给我解释一下BND导出捆绑包没有的api包背后的原理吗。对我来说这似乎是错误的,它总是(AFAICT)导致ClassNotFoundException 特别是 捆绑包A包含com.foo.api.MyInterface bundle B包含com.foo.impl.InterfaceImpl,它实现了MyInterface 因此,如果我告诉bnd导出捆绑包A中的包com.foo,他将正确导出com.foo.api,但如果我在捆绑包B中告诉导出包com.foo,它将错误导出com.foo.a

有人能给我解释一下BND导出捆绑包没有的api包背后的原理吗。对我来说这似乎是错误的,它总是(AFAICT)导致ClassNotFoundException

特别是
捆绑包A包含
com.foo.api.MyInterface

bundle B包含
com.foo.impl.InterfaceImpl
,它实现了
MyInterface

因此,如果我告诉bnd导出捆绑包A中的包
com.foo
,他将正确导出
com.foo.api
,但如果我在捆绑包B中告诉导出包
com.foo
,它将错误导出
com.foo.api
,因此MyInterface的使用者将连接到捆绑包B,然后在运行时获得ClassNotFoundException

为什么BND不能保证当一个包导出一个包时,它实际上包含了它


我知道,如果我导出
com.foo.api
com.foo.impl
而不仅仅是
com.foo
,那么这个问题在我的小例子中就解决了,但在我们的实际系统中,这并不是一个可能的问题。此外,实际的问题是BND为什么这样做,而不是如何解决问题。我已经知道解决这个问题的变通方法了

我还没有直接使用bnd,而是通过maven bundle插件来使用,该插件应该相当类似。我发现,如果您导出一个您没有的包,那么bnd将把这个包的类嵌入到您的bundle jar中

因此,至少在使用maven bundle插件时,bundle B应该在定义com.foo.api导出时嵌入接口。不确定当您仅将父包定义为导出时会发生什么,但我假设也会发生同样的情况


如果您希望将api与每个捆绑包一起部署(我不经常这样做,但这似乎是OSGi中的一种最佳实践(例如,对于实现OSGi api的捆绑包),这种自动嵌入非常有用。

这只是bnd语法的一个特性。因为bnd可以选择嵌入导入的包,所以在确定导出包和私有包头时,它会考虑整个类路径。Bnd不区分物理上位于正在处理的文件夹本地的类和类路径上其他地方的类


所以,如果您的Export Package语句包含bnd知道的包,bnd将假定您想要嵌入并导出它们。不过,我很惊讶您会看到异常,因为bnd也应该在打包包中物理地包含导出的类。

您是否查看了包B中的com.foo.api不在其中?如果您告诉bnd bundle B应该导出com.foo.api,那么bnd实际上会将该包放入bundle B中,然后将其导出。bnd有“能力”在生成的bundle中包含-buildpath中任意位置的类。我认为您确实不希望bundle B包含并导出com.foo.api,因此您应该修改bnd文件以删除导出语句。

我确实查看了。问题在于我没有使用maven bundle插件生成的JAR运行。我使用分解的jar运行,其中只有清单由BND创建,因此外部类不在target/classes文件夹中