通过类加载机制实现加载相同包名和类名的不同版本的类
有些地方有这种需求,要同时用到两个不兼容的jar包版本的某个工具类,它们的包名和类名又是一样的,即比如都叫org.xxx.Foo;
在项目里已经用到了该jar包的1.0版本,但是现在新的需求要用该jar包的2.0版本,但是2.0版本的jar包的工具类也是叫org.xxx.Foo;
这就导致了需要同时加载这两个签名一样的类(无法改造为一个jar,领导不允许)
可以用URLClassLoader实现:
package org;
import java.io.File;
import java.lang.reflect.Method;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class Main {
public static void main(String[] args) throws Exception {
File jar1 = new File("E:\\Projects\\bcprovextjdk15on_unionpay\\out\\artifacts\\jar1.jar");
File jar2 = new File("E:\\Projects\\bcprovextjdk15on_unionpay\\out\\artifacts\\jar2.jar");
JarURLClassLoader loader1 = new JarURLClassLoader(jar1.toURI().toURL());
JarURLClassLoader loader2 = new JarURLClassLoader(jar2.toURI().toURL());
Class<?> clazzTest1 = loader1.loadClass("me.silentdoer.Test");
Class<?> clazzTest2 = loader2.loadClass("me.silentdoer.Test");
Object o1 = clazzTest1.newInstance();
System.err.println(o1.getClass());
Method prints1 = clazzTest1.getMethod("prints");
prints1.invoke(o1);
Object o2 = clazzTest2.newInstance();
System.err.println(o2.getClass());
Method prints2 = clazzTest2.getMethod("prints");
prints2.invoke(o2);
}
public static class JarURLClassLoader {
private URL jar;
private URLClassLoader classLoader;
public JarURLClassLoader(URL jar) {
this.jar = jar;
classLoader = new URLClassLoader(new URL[]{jar});
}
/**
* 加载类,如:me.silentdoer.AClass
*
* @param name
* @return
*/
private Class<?> loadClass(String name) {
try {
return classLoader.loadClass(name);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
/**
* 在指定包路径下加载子类
*
* @param superClass
* @param basePackage
* @return
*/
public Set<Class> loadClass(Class<?> superClass, String basePackage) {
JarFile jarFile;
try {
// 将jar文件的URL转换为JarFile对象
jarFile = ((JarURLConnection) jar.openConnection()).getJarFile();
} catch (Exception e) {
e.printStackTrace();
return null;
}
return loadClassFromJar(superClass, basePackage, jarFile);
}
private Set<Class> loadClassFromJar(Class<?> superClass, String basePackage, JarFile jar) {
Set<Class> classes = new HashSet<>();
String pkgPath = basePackage.replace(".", "/");
Enumeration<JarEntry> entries = jar.entries();
Class<?> clazz;
while (entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement();
String entryName = jarEntry.getName();
if (entryName.charAt(0) == '/') {
entryName = entryName.substring(1);
}
if (jarEntry.isDirectory() || !entryName.startsWith(pkgPath) || !entryName.endsWith(".class")) {
continue;
}
String className = entryName.substring(0, entryName.length() - 6);
clazz = loadClass(className.replace("/", "."));
if (clazz != null && !clazz.isInterface() && superClass.isAssignableFrom(clazz)) {
classes.add(clazz);
}
}
return classes;
}
}
}
posted on 2022-11-28 23:08 Silentdoer 阅读(225) 评论(0) 编辑 收藏 举报