如何从 OSGi 运行时环境中按类名字符串加载类



我正在制作一个捆绑包来插入OSGi以为用户提供功能:

Usercase: User input the classname string and click "list" button, the corresponding class will be decompiled and show the text on GUI for user.

所以这是我的问题:我只有我的捆绑包的类加载器,我如何获得可以从整个OSGi容器中按名称加载类的OSGi容器类加载器?(我希望当OSGi启动时,它会将所有捆绑包和所有类加载到内存中,如果OSGi容器类加载器确实存在并且能够加载任何类,则可以加载任何类)

有人知道如何做这项工作吗?示例代码非常受欢迎。

我可以看到两种可能的情况可以帮助您。

任何可见类

您可以添加类似

DynamicImport-Package: *

到清单,然后尝试使用

Class.forName("com.company.class");

所有类,无论是否导出

如果你真的需要找到每个可用的类,我不确定你为什么要这样做,但你可以尝试询问每个捆绑包是否"知道"一个给定的类。由于在这种情况下,您最终可能会得到多个同名的类,因此由您来选择正确的类。

你可以做类似的事情

private List<Class<?>> findClass(BundleContext context, String name) {
    List<Class<?>> result = new ArrayList<Class<?>>();
    for (Bundle b : context.getBundles()) {
        try {
            Class<?> c = b.loadClass(name);
            result.add(c);
        } catch (ClassNotFoundException e) {
            // No problem, this bundle doesn't have the class
        }
    }
    return result;
}

在OSGi中,没有确定的方法只能通过完全限定的类名来命名类。原因是两个捆绑包可以用不同的方式定义相同的类名。例如,如果捆绑包 A 需要 lib v1.0,而捆绑包 B 在 2.0 版中需要相同的库,这一点很重要。

如果您也知道捆绑包,则可以命名一个类。所以你可以解决来自(捆绑包,字符串 fq类名)的类

您可以使用 BundleContext 实现这一点。从捆绑包上下文中,您可以列出捆绑包,并且对于每个捆绑包,您可以加载一个类。

当然,您也可以简单地遍历所有这些类加载器,并尝试按名称查找类。问题是,它不一定是唯一的。因为您可以在您的情况下打印警告,这可能没问题。

因此,您需要的关键 API 方法是:Bundle[] BundleContext.getBundles()Class Bundle.loadClass()

我不完全确定您要做什么,但是假设您正在构建一个工具,该工具需要在OSGi框架中安装时对所有应用程序包进行某种形式的处理,您可能需要考虑OSGi扩展器模式

  • The OSGi Extender Model,作者:Peter Kriens
  • OSGi 4.2: Extender Pattern and BundleTracker,作者:Kai Tödter
  • Extender Pattern with Automatic Servlet Registration,作者:Peter Kriens

我想您在捆绑包的清单中有一个导入指令来获取所需的软件包。如果这样做了,那么你正在寻找的所有类都应该是你的类加载器的一部分,并且按名称加载一个类应该可以工作。

那么,你确定你在 META-INF/MANIFEST 中有这样的东西吗?捆绑包中的 MF:

Import-Package: foo.bar.com;

最新更新