行。所以我有一个org.osgi.framework.launch.Framework,我通过以下方式以编程方式创建。
framework = ServiceLoader.load(FrameworkFactory.class).iterator().next().newFramework(getFrameworkConfig());
framework.start();
installBundles(BUNDLES_PATH); // installs bundles from a directory, by searching BUNDLES_PATH recursively for JARs
我想要做的是,有一个通用的loadClass方法(作为这个类中的方法)它将扫描已安装的bundle,读取它们的Export-Package:声明,并根据packageName调用正确的bundle的loadClass方法我作为参数传递的类。
有一种聪明的方法吗?或者这样做更好:
Class<?> c = null;
// else try every installed bundle one-by-one
for (Bundle bundle : framework.getBundleContext().getBundles()) {
try {
c = bundle.loadClass(className);
} catch (ClassNotFoundException e) {
// OK, move onto next bundle
continue;
}
if (c != null)
break;
}
return c;
我意识到我可以使用服务来让bundle发布他们的可用服务并让框架使用getAllServiceReferences()来查询服务,但这对程序员来说是更多的工作,而且我不确定我是否想要去声明性服务。
答案 0 :(得分:2)
我会提醒我不要采用这种方法。 OSGi框架可以包含多个提供者或包的版本。尝试制作一个能够正确处理这个问题的统一类加载器并非易事。但是,如果要查询正在导出的包,则有两个选项,具体取决于您使用的OSGi版本。
如果您在OSGi R4.3之前使用OSGi,则可以使用PackageAdmin。这是在服务注册表中注册的服务,允许您查询框架中捆绑包导出的包。您特别感兴趣的是getExportedPackage方法。这允许您选择包的提供者,然后您可以在提供包的包上调用loadClass。
在R4.3中不推荐使用PackageAdmin(尽管equinox仍在实现它)。这更复杂。要做你想做的事,你需要使用新的BundleWiring API。这包括获取系统中的每个捆绑包并执行以下操作:
BundleWiring bw = bundle.adapt(BundleWiring.class);
List<BundleCapability> capabilities = bw.getCapabilities(BundleRevision.PACKAGE_NAMESPACE);
for (BundleCapability bc : capabilities) {
String pkg = bc.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE);
}
在这种情况下你需要处理多个提供者并选择正确的提供者。找出正确的方法是困难的部分。