我有一个名为bundleA
的活动包,它使用另一个包中名为Example
的方法实现了一个名为doSomething()
的类。 ExampleImpl
实施Example
并通过ServiceLoader
加载(感谢SPI Fly)。在来自ExampleImpl.doSomething()
的{{1}}中,我需要获取名为bundleA
的捆绑的BundleWiring
(不传递doSomething()
或Bundle
,因为我不能改变API)。我可以获得BundleContext
bundleA
,但不能获得调用包BundleWiring
:
BundleWiring
如何获取调用包Bundle bundleA = FrameworkUtil.getBundle(ExampleClass.class);
BundleWiring bundleWiringOfBundleA = bundle.adapt(BundleWiring.class);
?
在我的特定情况下,调用包将始终是一个WAB,恰好在Liferay Portal 7.0中运行。因此,如果有专门针对Liferay Portal的解决方案,我会接受,但更通用的OSGi解决方案也可以。
请注意,我希望调用捆绑包的捆绑不是依赖于当前捆绑连接的每个捆绑包的捆绑连接。我知道我可以获得依赖于当前捆绑线路的捆绑接线,但这不能帮助我专门获得呼叫捆绑包:
BundleWiring
答案 0 :(得分:0)
你不能这样做。 OSGi根本不介入跨包方法调用,因此唯一可以用来尝试获取此信息的是使用Thread.currentThread().getStackTrace()
访问的Java调用堆栈。但是,此返回的StackTraceElement
对象仅为您提供类名而不是java.lang.Class
个对象,因此无法将这些对象关联回包。
除了不可能之外,我非常怀疑这将是一个好主意。你根本不应该导出实现类,更不用说尝试使它们对调用者敏感了。
如果您需要实现对调用bundle敏感的行为,那么实现该行为的规范和正确方法是使用ServiceFactory
接口注册服务。
答案 1 :(得分:0)
您可以使用BundleTracker并对正在安装的所有WAB做出反应。然后,您可以内省每个WAB,例如扫描注释类。
声明性服务和现有的WAB支持以这种方式工作。编写这样的扩展器并不容易。
答案 2 :(得分:0)
您说您无法更改API。但你可以改变呼叫捆绑吗?如果是这样,那么你可以拥有一个"代理"调用包使用而不是原始服务的服务。然后,您可以将Bundle
和/或BundleContext
传递给代理服务,并将您的依赖逻辑放在那里。
我想到的另一个选择是使用ThreadLocal
变量将此信息传递给被调用的包,但我不确定该方法可能产生的副作用。
答案 3 :(得分:0)
在Liferay中,致电WAB的${..}
存储在BundleContext
ServletContext
中:
"osgi-bundlecontext"
因此,只要您有权访问Liferay中的BundleContext bundleContext = servletContext.getAttribute("osgi-bundlecontext");
Bundle bundle = bundleContext.getBundle();
BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
,就可以获得调用包ServletContext
和Bundle
。