簡體   English   中英

如何從java maven項目中的兩個不同版本的jar加載類的兩個版本?

[英]How to load two versions of a class from two different versions of jars in a java maven project?

我有一個Maven項目,該項目依賴於版本“ 2.0”的jar“樣本”。 版本“ 2.0”的“示例” 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加載類。 公共ClassLoader.loadClass(String)方法調用受保護的ClassLoader.loadClass(String, boolean)方法,並且記錄了該方法的解釋以解釋始終總是首先搜索父類加載器。 當然,您可以通過URLClassLoader並重寫loadClass(String, boolean)方法來覆蓋此行為。

org.sample.SampleEnum從樣品-1.0.jar

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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM