1

好的。所以我有一个 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 方法(作为此类中的一个方法),它将扫描已安装的包,读取它们的 Export-Package: 声明,并根据类的 packageName 调用正确的包的 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;

我意识到我可以使用服务让捆绑包发布其可用服务并让框架使用 getAllServiceReferences() 查询服务,但这对程序员来说工作量更大,我不确定我是否想走声明式服务的路线。

4

1 回答 1

2

我会告诫不要采取这种方法。一个 OSGi 框架可以包含一个包的多个提供者或版本。尝试制作一个能够正确处理此问题的统一类加载器并非易事。但是,如果您想查询正在导出的包,您有两个选项,具体取决于您使用的 OSGi 版本。

如果您使用的是 OSGi R4.3 之前的 OSGi,则可以使用PackageAdmin。这是在服务注册表中注册的服务,允许您查询框架中的捆绑包导出了哪些包。您特别感兴趣的是getExportedPackage方法。这允许您选择包的提供者,然后您可以在提供包的包上调用 loadClass。

PackageAdmin 在 R4.3 中已被弃用(尽管 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);
}

在这种情况下,您需要处理多个提供者并选择正确的提供者。找出正确的部分是困难的部分。

于 2011-08-31T01:18:32.473 回答