简体   繁体   English

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

[英]How to load a class by classname string from OSGi runtime environment?

I'm making a bundle to plug on OSGi to provide user a function: 我正在制作一个插件来插入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.

So here is my problem: I only have the classloader of my bundle, how can I get the OSGi container classloader that I can load the class by name from the whole OSGi container? 所以这是我的问题:我只有我的bundle的类加载器,如何获得OSGi容器类加载器,我可以从整个OSGi容器中按名称加载类? (I expect that when OSGi starts, it will load all the bundles and all the class to memory, any class can be loaded by OSGi container classloader if it really exists and able to) (我希望当OSGi启动时,它会将所有bundle和所有类加载到内存中,如果OSGi容器类加载器确实存在且能够加载任何类,则可以加载它们)

Anyone knows how to do this job? 谁知道怎么做这个工作? Sample codes are highly appreciated. 示例代码非常受欢迎。

I can see two possible situations that could help you. 我可以看到两种可能对你有帮助的情况。

Any visible class 任何可见的类

You can add a statement like 您可以添加类似的语句

DynamicImport-Package: *

to your manifest, and then try to load the class using 到您的清单,然后尝试使用加载类

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

All classes, exported or not 所有课程,出口与否

If you really need to find every available class, I'm not sure why you would want this, but you could try asking each bundle whether it 'knows' a given class. 如果你真的需要找到所有可用的课程,我不确定你为什么要这样,但是你可以尝试询问每个包是否“知道”给定的课程。 Since in this situation you could end up with multiple classes with the same name, it's up to you to pick the right one. 因为在这种情况下你可能会得到多个具有相同名称的类,所以你可以选择正确的类。

You could do something like 你可以做点什么

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;
}

There is no sure way in OSGi to name a class only by its fully qualified class name. 在OSGi中,没有确定的方法只能通过其完全限定的类名来命名类。 The reason is that two bundles can define the same class name in a different way. 原因是两个包可以以不同的方式定义相同的类名。 This is for example important if bundle A needs a lib v1.0 and bundle B needs the same lib in version 2.0. 例如,如果bundle A需要lib v1.0而bundle B需要版本2.0中的相同lib,那么这很重要。

It is possible though to name a class if you also know the bundle. 如果您也知道捆绑包,则可以命名一个类。 So you could resolve a class from (Bundle bundle, String fqClassname) 所以你可以从(Bundle bundle,String fqClassname)解析一个类

You can implement this by using the BundleContext. 您可以使用BundleContext实现此功能。 From the bundle context you can list the bundles and for each bundle you can load a class. 从捆绑上下文中,您可以列出捆绑包,并为每个捆绑包添加类。

Of course you could then also simply iterate over all those class loaders and try to find the class by name. 当然,您也可以简单地遍历所有类加载器并尝试按名称查找类。 The problem is though that it does not have to be unique. 问题是它不必是唯一的。 As you can print a warning in your case that might be ok. 因为你可以在你的情况下打印一个可能没问题的警告。

So the key API methods you need are: Bundle[] BundleContext.getBundles() Class Bundle.loadClass() 所以你需要的关键API方法是:Bundle [] BundleContext.getBundles()Class Bundle.loadClass()

I am not entirely sure of what you are trying to do, but assuming you are building a tool that needs to do some form of processing on all application bundles while being installed in the OSGi framework, you may want to consider the OSGi Extender Pattern 我不完全确定你要做什么,但假设你正在构建一个工具,需要在安装在OSGi框架中的所有应用程序包上进行某种形式的处理,你可能想要考虑OSGi Extender模式

I suppose you have an import directive in your bundle's manifest to get the packages you need in. If that's done, then all the classes you are looking for ought to be part of your classloader, and loading a class by name should work. 我想你的bundle的清单中有一个import指令来获取你需要的包。如果已经完成,那么你要查找的所有类应该是你的类加载器的一部分,并且按名称加载一个类应该有用。

So, are you sure that you have something like this in META-INF/MANIFEST.MF in your bundle: 那么,你确定在捆绑中的META-INF / MANIFEST.MF中有这样的东西:

Import-Package: foo.bar.com;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM