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

我使用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”)

”)。但是,对于已发布的插件,不需要(要构建插件/捆绑,请执行“导出”->“可部署的插件和片段”)。

以上是 在Eclipse插件中使用反射库时不起作用 的全部内容, 来源链接: utcz.com/qa/419538.html

回到顶部