OSGi:以编程方式将导入添加到包中
如何从代码中将包添加到捆绑包的导入中?我需要它,因为我使用依赖反射并需要其他包的库,并且我不想为我开发的每个包手动将这些包添加到 MANIFEST.MF
How can I add packages to a bundle's import from within code? I need it since I use libraries which rely on reflection and require other packages and I don't want to need to manually add those packages to MANIFEST.MF for each bundle I develop
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你不能。
导入包在解决阶段进行评估。 (阶段已安装 -> 已解决 -> 活动)。
您的代码在捆绑包处于活动状态时执行,因此添加导入包为时已晚。
您可以执行 2 件事:
You cannot.
Import-Packages are evaluated in the Resolution phase. (Phases are Installed -> Resolved -> Active ).
Your code is executed when the bundle is Active, therefore too late to add Import-Packages.
You can do 2 things:
除了 Filippo 的解决方案之外,您还可以尝试反转依赖关系。 Fi 您可以让捆绑包执行此操作,而不是调用和检查其他捆绑包。另一种方法是使用捆绑包跟踪器并获取所跟踪捆绑包的类加载器。使用这个类加载器,您可以充当“捆绑包”,因此您不再需要 Import-Package 子句。
当我开始使用 OSGi 时,这是我首先提出的要求之一。随着时间的推移,我意识到几乎在所有情况下,都有一个更干净、更一致的解决方案。所以,想一想,你是否真的需要这种依赖。是否没有办法反转或抽象它以创建通用解决方案?
如果没有任何帮助(作为最后的手段),您还可以(在内存中)创建一个片段,以核心包作为主机,提供所需的导入。 BundleContext 为您提供了一种从流加载包的方法。然后,您必须在主机包上更新并调用刷新包(通过 PackageAdmin 服务)才能获取更新的类加载器(意味着重新启动您的包)。不过,最后,您将可以访问所有包。
作为旁注,我不建议通过调整导入语句然后更新来操作您的主机包...这会使您的包不确定并且无法与签名的包一起使用。另外,这违背了人们对 OSGi 的期望(想象一下随着时间的推移,捆绑包不断增长......您也需要在某个时候缩小导入!!!)
干杯,
米尔科
In addition to Filippo's solution, you can try to invert the dependency. F.i. instead of calling and inspecting the other bundles, you can let the bundles do that. Another way would be using a bundle tracker and obtaining the ClassLoader of the Bundle tracked. With this class loader you can act "as the bundle", so you don't need the Import-Package clause anymore.
When I started using OSGi, this was one of the first requirements I came up. Over time, I realized that in almost all cases, there is a cleaner and more consistent solution. So, think about it, if you really need this dependency. Is there no way to invert or abstract it to create a generic solution?
If nothing helps (as a last resort), you can also create (in Memory) a fragment with your core bundle as host, providing the required imports. The BundleContext offers you a method to load a bundle from a stream. You then have to update and call refreshpackages(via PackageAdmin service) on your host bundle in order to get the updated ClassLoader (implies a restart of your bundle). However, at the end, you'll have access to all your packages.
As a side note, I would not recommend to manipulate your host bundle by tweaking the import statement and then update... This renders your bundle indeterministic and won't work with signed bundles. Also, this is against everything one expects from OSGi (imagine a growing bundle over time... you need to shrink the imports at some point as well!!!)
Cheers,
Mirko