无法从 OSGI 包中获取 class 的类型化实例

Cannot get typed Instance of class from OSGI bundle

我有以下 situation.I 在我的应用程序中需要一个 class A 的实例,而这个 class A 来自 Bundle B (osgi) 并且位于包 X 中那个捆绑包。 到目前为止我做了什么: 我已将 bundle B 添加到本地 Maven 存储库,并将其作为 'provided' 范围的依赖项添加到我的 pom。 我还添加了 Bundle B 中的包 X,其中 class A 驻留在我的 pom 中,动态导入在我的 pom.xml 中。 这里要注意一件事——包 X 不是从 Bundle B 导出的,但我知道它仍然可以工作,我看到同事这样做了,但我还不是那么好。

无论如何,我是如何尝试获取下面 class 的实例的:

Bundle bundle;
Class<?> checkClass=bundle.loadClass("full path to class A");

TypeOfClassA newClass=checkClass.newInstance();

我得到了:

java.lang.ClassNotFoundException ClassA not found by myapplication
at 

org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1532) 在

org.apache.felix.framework.BundleWiringImpl.access400 美元(BundleWiringImpl.java:75)

但是为什么呢?我已经加载了 jar,我正在使用包 classloader,如果我将 checkClass 投射到 Object,我可以看到 Class A 的方法和字段,所以看起来不错,我如何获得 class A 的实例?

在 OSGi 中,编译时和运行时是有区别的。在编译时,您会看到您自己的 jar 的 classes 以及来自 maven 的所有依赖项。

在运行时,默认情况下一个包只能看到它自己的 classes。任何其他包都需要在清单中包含 Import-Package 语句。通常这是在你使用 class 时由 bnd 自动创建的。只要有可能,你就应该依靠这种自动化。

你的情况当然是不同的,因为你想要访问的包不是由 bundle B 导出的。在这种情况下,无法通过 bundle classloader 到达 class A你自己的包。

相反,您需要使用 bundle B 的 bundle classloader。例如,您可以从 BundleContext 获取 bundle B。然后你可以加载 class.

另一种选择是使用 Bundle B 中导出的 class C,并使用 class C 的 classloader 加载 class A。

无论如何,这是一个 hack。您应该避免使用另一个包的私有 classes。

当你写类似 PluginA test=(PluginA) classloader.loadclass("PluginA").newInstance() 然后你需要实际导入 PluginA class,正如 Christian 提到的,只有从它所在的包中导出它才有可能。以下应该有效:

Object test= classloader.loadclass("PluginA").newInstance()

然后您将需要使用反射来访问 class 等方法