Osgi 管理通过使用约束声明的可传递包依赖项

Osgi 管理通过使用约束声明的可传递包依赖项,osgi,apache-felix,Osgi,Apache Felix,我有捆绑包A、B和C。A包含一个包“A”,它分别由捆绑包B和C中的包B和C中的代码所依赖 bundle A { package a export-package:a } bundle B { package b.a package b.b package b.c package b.d package b.e import-package: a export-package:b.a;uses:=a, b.b;uses:=b.a, b.c;

我有捆绑包A、B和C。A包含一个包“A”,它分别由捆绑包B和C中的包B和C中的代码所依赖

bundle A {
  package a

  export-package:a
}

bundle B {
  package b.a
  package b.b
  package b.c
  package b.d
  package b.e

  import-package: a
  export-package:b.a;uses:=a,
    b.b;uses:=b.a,
    b.c;uses:=b.b,
    b.d;uses:=b.c,
    b.e;uses:=b.d
}

bundle C {
  package c

  import-package: b.e,
    a
}
当我一起更新所有这些捆绑包时,我经常会遇到违反约束的情况(Felix报告风格):

起初,我很惊讶b.e为“a”生成了uses子句。这不会在清单中声明,也不会在提供这些捆绑包的OBR repository.xml中声明。然而,b.e中的类型通过它们的API公开了a中的类型,所以我想这就是它的来源

我发现解决这些问题的唯一方法是增加中间包的导出和导入的版本号,例如本例中的b.e。然而,有很多软件包最终使用了“a”,可以传递


这意味着每次更新“a”时,我还需要使用新版本更新a上的所有可传递依赖项。增加这些软件包的版本号是否正确?重构代码以减少相互依赖性是唯一的其他方法吗?

解析程序不会传递使用约束

如果捆绑包C导入b.e和b.e使用的b.d,那么捆绑包C也需要导入b.d。也就是说,b.e的公共签名包括对b.d中某些内容的引用。这就是为什么我们说b.e使用b.d。因此,任何导入b.e的捆绑包也必须导入b.d。否则,捆绑包无法正确使用b.e,因为b.e中引用的某些类型对捆绑包不可见

对于b.e.的出口,它应该说明它使用b.d、b.c、b.b、b.a和a,因为使用b.d意味着你也使用b.c等等


您是否手工生成了uses子句?或者这个例子是由bnd生成的吗?

谢谢您的回答。否,uses子句是使用清单编辑器中的PDE生成的。对于b.e,a不包括在使用条款中,但b.d是。我认为是Felix通过[edit:实际上它可以通过API中的类型进行传递-将对此进行检查]。我认为更奇怪的是,b.e中没有任何东西在其API中公开来自a的任何内容。我需要检查的另一件事是OBR repository.xml,它可能将这些定义为需求/功能……我进一步查看了repository.xml。从b.e到a.e.没有任何进一步的要求。然而,b.e的API确实在其JavaAPI中公开了来自a的类型,所以我想这就是为什么uses子句由Felix“推断”的原因(没有正式声明)?感觉在这里管理多个软件包版本并进行这些“级联”版本更新的唯一方法是组合更多的软件包。。。虽然这感觉有点不对。请注意,uses约束冲突仅在运行时发生。重新启动时,新更新的捆绑包似乎一切正常。我不确定我会相信PDE的uses约束生成。(我承认自己是bndtools/bnd粉丝!)框架不会生成使用信息;他们只使用清单中提供的内容。如果提供部分信息,您可能会遇到麻烦。最后,来自“已使用”包的类型不需要在包中直接可见即可使用。考虑B.E.E,扩展B.D.D,扩展B.C.B.扩展B.B.扩展B.A。实现A.I.B.E将只显示直接引用B.D.D,但是继承层次都是“使用”的。
Chain 1:
  C [47.1]
    import: (&(osgi.wiring.package=a)(version>=1.1.0))
     |
    export: osgi.wiring.package=a
  A [9.1]

Chain 2:
  C [47.1]
    import: (&(osgi.wiring.package=b.e)(version>=1.0.0))
     |
    export: osgi.wiring.package=b.e; uses:=a
  B [33.0]
    import: (&(osgi.wiring.package=a)(version>=1.0.0))
     |
    export: osgi.wiring.package=a
  C [9.0]