java - 如何从java maven项目中的两个不同版本的jar加载一个类的两个版本?

标签 java maven jar

我有一个 Maven 项目,它依赖于版本“2.0”的 jar“样本”。 版本“2.0”的“sample”jar 包含一个名为“SampleEnum”的枚举。 “2.0”版本中的 SampleEnum 如下所示

public enum SampleEnum {
    "HERBIVORES",
    "CARNIVORES",
    "OMNIVORES"
}

我想从上面提到的maven java项目中版本“1.0”的“sample”jar中加载“SampleEnum”类。 “1.0”版本中的 SampleEnum 类如下所示。

public enum SampleEnum {
    "HERBIVORES",
    "CARNIVORES"
}

我使用下面的代码来加载该类:

public class Test
{
    public static void main(String args[]) {
        try {
            URLClassLoader loader1 = new URLClassLoader(new URL[] {new File("sample-1.0.jar").toURL()}, Thread.currentThread().getContextClassLoader());

            Class<?> c1 = loader1.loadClass("SampleEnum");

            for (Object o : c1.getEnumConstants()) {
                System.out.println(o);
            }
        }
        catch(Exception ex)
        {
            System.err.println(ex.getMessage());
        }
    }
}

上述程序的实际输出是:

草食动物 食肉动物 杂食动物

当我从“sample-1.0”jar 加载类时,我期望得到以下输出:

草食动物 食肉动物

我可以知道为什么它从依赖的jar而不是指定的jar加载类吗?

有没有办法从maven项目中的1.0版本jar中加载枚举类?

最佳答案

它从依赖的jar加载类的原因是因为loader1类加载器获取当前线程的上下文类加载器作为其父类加载器,并且该类加载器从依赖的jar加载类。公共(public) ClassLoader.loadClass(String) 方法调用 protected ClassLoader.loadClass(String, boolean) 方法,并且记录该方法以解释父类加载器始终是首先搜索。当然,您可以通过子类化 URLClassLoader 并覆盖 loadClass(String, boolean) 方法来覆盖此行为。

来自sample-1.0.jar的

org.sample.SampleEnum

public enum SampleEnum
{
    HERBIVORES,
    CARNIVORES
}
来自sample-2.0.jar的

org.sample.SampleEnum

public enum SampleEnum
{
    HERBIVORES,
    CARNIVORES,
    OMNIVORES
}

Main.java

package com.example.app;

import org.sample.SampleEnum;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;

import static java.util.Arrays.asList;

public class Main
{
    public static void main(String[] args)
    {
        System.out.println("v2.0: " + asList(SampleEnum.values()));
        try {
            URLClassLoader loader1 = new CustomURLClassLoader(
                    new URL[] { new File("../sample-1.0/target/sample-1.0.jar").toURL() });

            Class<?> c1 = loader1.loadClass("org.sample.SampleEnum");

            System.out.println("v1.0: " + asList(c1.getEnumConstants()));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

class CustomURLClassLoader extends URLClassLoader
{
    public CustomURLClassLoader(URL[] urls)
    {
        super(urls);
    }

    protected Class<?> loadClass(String name, boolean resolve)
            throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();

                // First, look in the current ClassLoader
                long t1 = System.nanoTime();
                try {
                    c = findClass(name);
                } catch (ClassNotFoundException ex) {
                    // ClassNotFoundException thrown if class not found
                }

                // this is the defining class loader; record the stats
                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                sun.misc.PerfCounter.getFindClasses().increment();

                // Lastly, look in the parent ClassLoader
                try {
                    if (getParent() != null) {
                        c = super.loadClass(name, resolve);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }
}

输出:

$ java -cp sample-app-2.0.jar:sample-2.0.jar com.example.app.Main
v2.0: [HERBIVORES, CARNIVORES, OMNIVORES]
v1.0: [HERBIVORES, CARNIVORES]

有关详细信息,请参阅https://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html#loadClass(java.lang.String,%20boolean)

关于java - 如何从java maven项目中的两个不同版本的jar加载一个类的两个版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41814398/

相关文章:

java - 尝试将自定义对象写入outputStream时出现java.io.NotSerializedException

Java正则表达式匹配

java - Maven 上的 POM 是什么?

Clojure 中的 Java 等效开关?

java - 与 Java 的 SSH 连接

postgresql - 无法实例化 SpatialIntegrator

java - 为 SonarPython 编写一个插件

java - 如何仅使用命令行运行 Maven 创建的 jar 文件

java - 创建包含外部文本和 ser 文件的可运行 Jar

java - 如何使(JAR)文件能够访问应用程序所需的外部文件夹?