【问题标题】:Java Annotations don't work with external Jar FilesJava 注释不适用于外部 Jar 文件
【发布时间】:2012-10-27 16:23:24
【问题描述】:

所以,我目前正在为我的命令行“操作系统”开发插件系统(插件是位于插件文件夹中的 jar 文件)。工作正常,但 API 不行。

我正在使用注释来获取插件主类和事件类。但是,它似乎没有找到我的注释。

这是我用来加载我的插件的:

public static void loadPlugin(File file)
{
    try
    {
        URL urlList[] =
        { new File("plugins/" + file.getName()).toURI().toURL() };
        URLClassLoader classLoader = new URLClassLoader(urlList);
        Class<?> pluginclass, eventclass = pluginclass = null;
        String name, version = name = null;
        Priority priority = Priority.NORMAL;

        String[] classes = Utils.getJarClasses(file, "plugin").toArray(new String[]
        {});

        for (String s : classes)
        {
            System.out.println(s);
            Class<?> c = classLoader.loadClass(s);
            Plugin p = c.getAnnotation(Plugin.class);
            EventHandler e = c.getAnnotation(EventHandler.class);

            if (p != null)
            {
                System.out.println("not null!");
                pluginclass = c;
                name = p.name();
                version = p.version();
                priority = p.priority();
            }

            if (e != null)
            {
                eventclass = c;
            }
        }

        switch (priority)
        {
        case NORMAL:
            plugins.add(new Class<?>[]
            { pluginclass, eventclass });
        case DEVELOPER_API:
            apis.add(new Class<?>[]
            { pluginclass, eventclass });
        }
        print("Loaded Plugin: " + name + " V" + version + " with priority " + priority.toString() + ".");
    } catch (Exception e)
    {
        e.printStackTrace();
    }
}

它正在打印出它当前循环的类,但是 pe 始终为空,无论如何。 versionname 显然也始终为空。

我的注释类有@Retention(RetentionPolicy.RUNTIME),这就是我在这里问的主要原因。

我测试了一个类似的系统,只是没有使用 jar 文件(而是包内的类)并且工作正常。

提前致谢。

【问题讨论】:

  • JVM 是否认为你的类有 any 注释? c.getAnnotations() 告诉你什么?我想知道这是否是类加载器问题,其中注释的类型为Plugin-loaded-by-CL1,而您要求的注释类型为Plugin-loaded-by-CL2...
  • String: [plugin.Events, plugin.CommandPing, plugin.Pinger] plugin.Events [] plugin.CommandPing [] plugin.Pinger [] 这就是它用 Arrays.toString 输出的,意思是,它什么都没有。
  • Utils.getJarClasses(..) 是做什么的?请至少通过编辑您的问题来显示该方法的代码,最好提供MCVE。然后在此处发表评论通知我们。

标签: java file jar annotations external


【解决方案1】:

可以解释所描述行为的一个原因是您正在混合类加载器:只有当注释类和被注释类型都由同一个类加载器加载时,注释才会可见。这与使用反射 API 作为实际执行注释查找过程所采用的机制有关。

在您的代码中,您使用自定义类加载器 classLoader 从外部 jar 文件加载类,但 PluginEventHandler 类均由运行您的 loadPlugin 的类加载器加载方法。

为了解决这个问题,我认为您可以提供运行loadPlugin 方法的类加载器作为自定义类加载器的父类加载器,例如:

URLClassLoader classLoader = new URLClassLoader(urlList, YourClass.class.getClassLoader());

以前在 stackoverflow 中也曾报告过类似的行为。例如,请参阅this questionthis other one 的接受答案。

【讨论】:

  • 我总是很遗憾看到人们努力编写一般性答案,因为 OP 不对任何问题(例如我的)做出反应,因此没有给任何人写具体答案的机会,让人们推测或写出像你这样好的但通用的答案,甚至没有得到评论的奖励,更不用说接受答案并给你全部赏金了。我想对你的努力表示敬意。我会写一个类似但更具体的答案,但想先等待 OP 的反应。我很高兴我没有在这上面浪费时间。
  • 感谢@kriegaex,非常感谢您的评论。不久前我开始在网站上回答问题,但尽管如此,我发现有时没有从你想帮助的人那里得到反馈有点令人沮丧。但是,嘿,它不应该让我们失望。再次感谢您
  • 谢谢!这非常有帮助。
  • 不客气@Hodglem。我很高兴听到这个答案很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-01
  • 1970-01-01
  • 2015-03-11
  • 2011-01-20
  • 1970-01-01
  • 2013-06-15
  • 2014-09-03
相关资源
最近更新 更多