当前位置: 首页 > 面试题库 >

在Eclipse插件中使用反射库时不起作用

文鸣
2023-03-14
问题内容

我使用Reflections库开发了一个应用程序,用于查询具有特定批注的所有类。直到我决定从我的应用程序创建Eclipse插件之前,一切都像魅力一样。然后反射停止工作。

鉴于我的应用程序在不属于Eclipse插件的情况下运行良好,因此我认为这应该是类加载器的问题。因此,我在我Reflections的类中添加了插件激活器类的类加载器,上下文类加载器以及我能想象的所有其他类加载器,但没有成功。这是我的代码的简化版本:

ConfigurationBuilder config = new ConfigurationBuilder();
config.addClassLoaders(thePluginActivatorClassLoader);
config.addClassLoaders(ClasspathHelper.getContextClassLoader());
config.addClassLoaders("all the classloaders I could imagine");
config.filterInputsBy(new FilterBuilder().include("package I want to analyze"));

Reflections reflections = new Reflections(config);
Set<Class<?>> classes = reflections.getTypesAnnotatedWith(MyAnnotation.class); //this Set is empty

我还尝试将要加载的ConfigurationBuilder类的URL添加到该类,但这没有帮助。

有人可以告诉我是否有一种方法可以使Reflections工作成为Eclipse插件的一部分,还是我应该更好地寻找另一种选择?非常感谢,对此我感到很困惑。


问题答案:

我假设您已经知道如何创建包(否则,请检查此)。

经过对Reflections API的调试和探索之后,我意识到问题是Reflections根本无法读取OSGi URL(bundleresource://
…),从而导致异常:

org.reflections.ReflectionsException: could not create Vfs.Dir from url, 
no matching UrlType was found [bundleresource://1009.fwk651584550/]

和这个建议:

either use fromURL(final URL url, final List<UrlType> urlTypes) 
or use the static setDefaultURLTypes(final List<UrlType> urlTypes) 
or addDefaultURLTypes(UrlType urlType) with your specialized UrlType.

因此,我相信为OSGi实现UrlType(例如class BundleUrlType implements UrlType {...})并像这样注册它:

Vfs.addDefaultURLTypes(new BundleUrlType());

应该从捆绑包内部使Reflections API可用。描述思考的依赖应该被添加到Eclipse插件项目
在这里

这是添加所需罐子后的示例MANIFEST.MF的样子:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: ReflectivePlugin
Bundle-SymbolicName: ReflectivePlugin
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: reflectiveplugin.Activator
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: javax.annotation;version="1.0.0",
 org.osgi.framework;version="1.3.0",
 org.osgi.service.log;version="1.3",
 org.osgi.util.tracker;version="1.3.1"
Bundle-ClassPath: .,
 lib/dom4j-1.6.1.jar,
 lib/guava-r08.jar,
 lib/javassist-3.12.1.GA.jar,
 lib/reflections-0.9.5.jar,
 lib/slf4j-api-1.6.1.jar,
 lib/xml-apis-1.0.b2.jar
Export-Package: reflectiveplugin, 
 reflectiveplugin.data

注意:Used Reflections v。0.9.5

这是一个示例UrlType实现:

package reflectiveplugin;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;

import org.osgi.framework.Bundle;
import org.reflections.vfs.Vfs;
import org.reflections.vfs.Vfs.Dir;
import org.reflections.vfs.Vfs.File;
import org.reflections.vfs.Vfs.UrlType;

import com.google.common.collect.AbstractIterator;

public class BundleUrlType implements UrlType {

    public static final String BUNDLE_PROTOCOL = "bundleresource";

    private final Bundle bundle;

    public BundleUrlType(Bundle bundle) {
        this.bundle = bundle;
    }

    @Override
    public boolean matches(URL url) {
        return BUNDLE_PROTOCOL.equals(url.getProtocol());
    }

    @Override
    public Dir createDir(URL url) {
        return new BundleDir(bundle, url);
    }

    public class BundleDir implements Dir {

        private String path;
        private final Bundle bundle;

        public BundleDir(Bundle bundle, URL url) {
            this(bundle, url.getPath());
        }

        public BundleDir(Bundle bundle, String p) {
            this.bundle = bundle;
            this.path = p;
            if (path.startsWith(BUNDLE_PROTOCOL + ":")) { 
                path = path.substring((BUNDLE_PROTOCOL + ":").length()); 
            }
        }

        @Override
        public String getPath() {
            return path;
        }

        @Override
        public Iterable<File> getFiles() {
            return new Iterable<Vfs.File>() {
                public Iterator<Vfs.File> iterator() {
                    return new AbstractIterator<Vfs.File>() {
                        final Enumeration<URL> entries = bundle.findEntries(path, "*.class", true);

                        protected Vfs.File computeNext() {
                            return entries.hasMoreElements() ? new BundleFile(BundleDir.this, entries.nextElement()) : endOfData();
                        }
                    };
                }
            };
        }

        @Override
        public void close() { }
    }

    public class BundleFile implements File {

        private final BundleDir dir;
        private final String name;
        private final URL url;

        public BundleFile(BundleDir dir, URL url) {
            this.dir = dir;
            this.url = url;
            String path = url.getFile();
            this.name = path.substring(path.lastIndexOf("/") + 1);
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public String getRelativePath() {
            return getFullPath().substring(dir.getPath().length());
        }

        @Override
        public String getFullPath() {
            return url.getFile();
        }

        @Override
        public InputStream openInputStream() throws IOException {
            return url.openStream();
        }
    }
}

这就是我在Activator类中创建反射的方法:

private Reflections createReflections(Bundle bundle) {
    Vfs.addDefaultURLTypes(new BundleUrlType(bundle));
    Reflections reflections = new Reflections(new Object[] { "reflectiveplugin.data" });
    return reflections;
}

最后一点非常令人困惑,但仍然很重要:如果您在Eclipse(运行方式为/ OSGi
Framework)中运行插件,则还必须将类输出目录添加到Reflections路径模式(即“ bin”或“ target / classes”)
”)。但是,对于已发布的插件,不需要(要构建插件/捆绑,请执行“导出”->“可部署的插件和片段”)。



 类似资料:
  • 我的Java(64位)版本信息如下: 我的应用程序有很多实例,因此如果每个引用占用8个字节,它会消耗大量内存。所以我想使用-XX: UseCompressedOops来强制JVM压缩OOP。在eclipse中,我在运行配置中的VM Arguments中添加了-XX: UseCompressedOops。 但是,当我使用 VisualVM 1.3.7 分析我的程序时,我仍然得到的结果是每个引用的大小

  • 问题内容: 我试图使用React中的dragonallySetInnerHTML属性设置从服务器发送的html以显示在div中。我里面也有script标签,并使用在html内相同定义的函数。我在这里在JSFiddle中给出了错误示例。 这是测试代码: 我检查了该脚本标记并将其添加到DOM,但是无法调用该脚本标记中定义的功能。如果这不是正确的方法,那么还有其他方法可以注入脚本标签的内容。 问题答案:

  • 问题内容: 当我在带有选项create emulator的Jenkins上运行测试时,出现以下问题: [android]无法创建Android模拟器:无法运行AVD创建命令 当我以现有仿真器为目标时,会遇到以下问题: 致命:C:\ Windows \ system32 \ config \ systemprofile.android \ avd \ AVD_2.2.ini(系统找不到指定的路径)j

  • 问题内容: 我通过以下方式添加了一个 关闭钩子 : 它正常工作,但是当我单击Eclipse中的红色停止按钮时,它不能正常工作。有没有办法在Eclipse中调用shutdown钩子? 问题答案: 红色的停止按钮会强行杀死应用程序,即无法正常运行,因此JVM不知道应用程序正在退出,因此不会调用关闭挂钩。 不幸的是,没有办法(至少在Windows中)提供一种机制来确保始终调用该挂钩。它只是可以被调用的东

  • 问题内容: 我是新来的人,我想做出反应并尝试使用内联样式获取背景图片。但这不起作用。 显示错误“ URL未定义” 问题答案: CSS值始终是字符串。将值用引号引起来,使其成为字符串:

  • 我想将视图渲染为pdf,并尝试使用Grails渲染插件2.0.3 我尝试了最简单的gsp-file开始: 在控制器中: 最后是: 我错过了什么?或者它不应该与这个版本的grails(3.2.4)一起使用? 也许有更好的插件可以使用?