我有一个 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)
方法来覆盖此行为。
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]
关于java - 如何从java maven项目中的两个不同版本的jar加载一个类的两个版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41814398/