描述
之前直接继承ClassLoader, 单独加载类,且有依赖的时候会比较麻烦。
此处使用URLClassLoader(ClassLoader的子类SecureClassLoader的子类)加载整个lib,并调用其中的方法。这样即使jar包有多个版本,且我们都想要使用其中的方法,也可以满足。
代码
package com.hz.classloader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
/**
* @description: 使用URLClassLoader加载
* @author: pp_lan
* @date: 2022/3/17
*/
public class UrlExternalClasspathLoader {
private static final Logger LOGGER = LoggerFactory.getLogger(UrlExternalClasspathLoader.class);
private URLClassLoader urlClassLoader;
/**
* 构造方法
* @param file jar所在的路径,或者单个jar的全路径
*/
public UrlExternalClasspathLoader(File file) {
List<URL> urlList = new ArrayList<>();
if (file.isDirectory()) {
addUrl(urlList, file);
} else {
addJar(urlList, file);
}
URL[] urls = urlList.toArray(new URL[]{});
urlClassLoader = new URLClassLoader(urls);
}
/**
* 加载class
* @param name
* @return
* @throws ClassNotFoundException
*/
public Class<?> loadClass(String name) throws ClassNotFoundException {
return this.urlClassLoader.loadClass(name);
}
/**
* 加载路径
* @param urlList
* @param file
*/
private void addUrl(List<URL> urlList, File file) {
File[] subFiles = file.listFiles();
if (subFiles != null) {
for (File subFile : subFiles) {
if (subFile.isDirectory()) {
addUrl(urlList, subFile);
} else {
addJar(urlList, subFile);
}
}
}
}
/**
* 加载jar
* @param urlList
* @param subFile
*/
private void addJar(List<URL> urlList, File subFile) {
try {
if (subFile.getAbsolutePath().endsWith(".jar")) {
urlList.add(subFile.toURI().toURL());
}
} catch (MalformedURLException e) {
LOGGER.error("【加载JAR异常】", e);
}
}
public static void main(String[] args) {
LOGGER.info("开始");
UrlExternalClasspathLoader classLoader1 = new UrlExternalClasspathLoader(new File("E:\\git-workspace\\mercury-new\\app\\lib\\"));
UrlExternalClasspathLoader classLoader2 = new UrlExternalClasspathLoader(new File("E:\\git-workspace\\mercury-new\\app\\lib\\"));
try {
Class<?> aClass1 = classLoader1.loadClass("com.zzz.common.api.tool.ApiUtil");
Method nullOrEmpty1 = aClass1.getMethod("nullOrEmpty", String.class);
Object invoke11 = nullOrEmpty1.invoke(aClass1, "123");
Object invoke12 = nullOrEmpty1.invoke(aClass1, "");
Object invoke13 = nullOrEmpty1.invoke(aClass1, "null");
Class<?> aClass2 = classLoader2.loadClass("com.zzz.common.api.tool.ApiUtil");
Method nullOrEmpty2 = aClass2.getMethod("nullOrEmpty", String.class);
Object invoke21 = nullOrEmpty2.invoke(aClass1, "123");
// 执行结果
LOGGER.info("【结果】11: {}, 12: {}, 13: {}.", invoke11, invoke12, invoke13);
LOGGER.info("【结果】21: {}.", invoke21);
} catch (Exception e) {
LOGGER.error("ClassLoader调用方法失败", e);
}
}
}
说明
- 添加一个路径或者一个jar包,到URLClassLoader对象中,
- 使用时候直接调用loadClass方法获取Class对象
- 再使用反射进行调用