无法从 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 等方法
我有以下 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 等方法