7

我问是因为我完全不确定我做对了。我正在将 Eclipse 用于 Web 项目。我们称它为包中的 WebProject (duh) com.web.project

我希望 WebProject 在运行时加载 JAR 插件,所以我想我可以利用java.util.ServiceLoader. 所以我com.web.project.WebProjectPlugin在 WebProject 项目中创建了一个接口,其中包含插件必须实现的所有方法。

然后我创建了项目 PluginProject,在其构建路径中添加 WebProbject/build/classes 作为类文件夹:

package com.web.project.plugin;

import com.web.project.WebProjectPlugin;

public class TestPlugin implements WebProjectPlugin {
    // Implementation of the interface methods...
}

然后我在插件项目中创建了一个 META-INF/services 文件夹,将文本文件com.web.project.WebProjectPlugin放入其中,包含唯一的一行“com.web.project.plugin.TestPlugin”。

我导出了 JAR 文件,检查了添加的 build/classes 文件夹并将其放在硬盘驱动器的某个位置。当 WebProject 启动时,它会执行以下操作:

File[] jlist = pluginsDir.listFiles(new FileFilter() {
    public boolean accept(File file) {
        return file.getPath().toLowerCase().endsWith(".jar");
    }
});
URL[] urls = new URL[jlist.length];
for (int i = 0; i < jlist.length; i++)
    urls[i] = jlist[i].toURI().toURL();
URLClassLoader ucl = new URLClassLoader(urls);

ServiceLoader<WebProjectPlugin> srvl =
    ServiceLoader.load(WebProjectPlugin.class, ucl);
Iterator<WebProjectPlugin> iter = srvl.iterator();
while (iter.hasNext()) {
    WebProjectPlugin plugin = iter.next();
    plugins.add(plugin);
}

pluginsDir是一个File指向 JAR 文件所在目录的对象。起初它似乎srvl完成了它的工作,因为iter它不是空的,但是NoClassDefFoundError当它到达iter.next().

我已经设法创建了一个插件管理器项目来测试ServiceLoader,它运行得很好,但它是一个普通的控制台 Java 应用程序,而不是一个 Web 项目。那么,我在这里做错了什么?

我有点困惑:它怎么找不到的类定义com.web.project.WebProjectPlugin,因为它在同一个正在运行的项目中?这与URLClassLoader我正在使用的对象有关吗?

这是堆栈跟踪

4

1 回答 1

7

尝试将父类加载器分配给您的URLClassLoader

URLClassLoader loader = new URLClassLoader(urls, Thread.currentThread().getContextClassLoader());

WebProject 需要特定的类加载器层次结构,因此如果父/子层次结构设置不正确,您的类可能彼此不可见。

于 2013-04-30T08:09:23.540 回答