如何在OSGi中获取BundleWiring的调用Bundle?

问题描述 投票:1回答:4

我有一个名为bundleA的活动包,它使用另一个包中名为Example的方法实现了一个名为doSomething()的类。 ExampleImpl实施Example并通过ServiceLoader装载(感谢SPI Fly)。在来自ExampleImpl.doSomething()bundleA中,我需要得到BundleWiringdoSomething()(没有通过BundleBundleContext,因为我无法更改API)。我可以得到bundleABundleWiring,但不是调用包的BundleWiring

Bundle bundleA = FrameworkUtil.getBundle(ExampleClass.class);
BundleWiring bundleWiringOfBundleA = bundle.adapt(BundleWiring.class);

我怎样才能获得调用包的BundleWiring

在我的特定情况下,调用包将始终是一个恰好在Liferay Portal 7.0中运行的WAB。因此,如果有一个特定于Liferay Portal的解决方案,我会接受,但更通用的OSGi解决方案也可以。

请注意,我希望调用捆绑包的捆绑连接不是每个捆绑包的捆绑连接,这取决于当前捆绑连接。我知道我可以获得依赖于当前捆绑接线的捆绑接线,但这不能帮助我专门获取调用捆绑包:

Bundle bundleA = FrameworkUtil.getBundle(ExampleClass.class);
List<BundleWires> bundleWires =
    bundleWiring.getProvidedWires(BundleRevision.PACKAGE_NAMESPACE);
bundleWires.get(0).getRequirerWiring();
java liferay osgi liferay-7 wab
4个回答
0
投票

你不能这样做。 OSGi根本不介入跨包方法调用,因此您可以尝试获取此信息的唯一方法是使用Thread.currentThread().getStackTrace()访问的Java调用堆栈。但是,返回的StackTraceElement对象只会为您提供类名而不是java.lang.Class对象,因此无法将这些对象关联回束。

除了不可能,我非常怀疑这将是一个好主意。您根本不应该导出实现类,更不用说尝试使它们对调用者敏感。

如果您需要实现对调用bundle敏感的行为,那么实现该行为的规范和正确方法是使用ServiceFactory接口注册服务。


0
投票

您可以使用BundleTracker并对正在安装的所有WAB做出反应。然后,您可以内省每个WAB,例如扫描类以进行注释。

声明性服务和现有的WAB支持以这种方式工作。编写这样的扩展器并不容易。


0
投票

你说你不能改变API。但你可以改变呼叫捆绑吗?如果是这样,那么您可以使用“代理”服务来调用捆绑包而不是原始捆绑包。然后,您可以将Bundle和/或BundleContext传递给代理服务,并将您的依赖逻辑放在那里。

想到的另一个选择是使用ThreadLocal变量将此信息传递给被调用的bundle,但我不确定该方法可能具有哪些副作用。


0
投票

在Liferay中,调用WAB的BundleContext作为ServletContext存储在"osgi-bundlecontext"中:

BundleContext bundleContext = servletContext.getAttribute("osgi-bundlecontext");
Bundle bundle = bundleContext.getBundle();
BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);

因此,只要您可以访问Liferay中的ServletContext,您就可以获得调用包的BundleBundleWiring

© www.soinside.com 2019 - 2024. All rights reserved.