java通过URLClassLoader类加载器加载外部jar

文章讲述了在Java中如何使用URLClassLoader动态加载未添加到项目依赖的外部jar,并调用其内部方法。在加载过程中,如果外部jar有内部依赖,由于路径问题会导致NoClassDefFoundError。解决方案是将内部jar资源读出并写入本地文件系统,然后加载这些依赖。文章还提供了相关代码示例和打包配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    相信在实际工作中,大家可能会遇到这种需求,这个jar是外部的,并没有添加到项目依赖中,只能通过类加载器加载并调用相关方法。

    这种jar加载,其实也简单,我们通过普通的URLClassLoader就可以加载。代码如下所示:

public static URLClassLoader getClassLoader(String url) {
    URLClassLoader classLoader = new URLClassLoader(new URL[]{}, ClassLoader.getSystemClassLoader());
    try {
        Method method = URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{URL.class});
        if (!method.isAccessible()) {
            method.setAccessible(true);
        }
        method.invoke(classLoader, new URL("file:" + url));
        return classLoader;
    } catch (NoSuchMethodException | MalformedURLException | InvocationTargetException | IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}

    这里,只是把jar加载到了虚拟机中,要调用,我们需要根据类名与类加载器来 获取类对象。

public static List<Class<?>> getClassListByInterface(String url, ClassLoader classLoader, Class<?> clazz) {
	List<Class<?>> classList = new ArrayList<>();
	if (!clazz.isInterface()) {
		return classList;
	}
	List<String> classNames = new ArrayList<>();
	try (JarFile jarFile = new JarFile(url)) {
		Enumeration<JarEntry> entries = jarFile.entries();
		while (entries.hasMoreElements()) {
			JarEntry jarEntry = entries.nextElement();
			String entryName = jarEntry.getName();
			if (entryName != null && entryName.endsWith(".class")) {
				entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."));
				classNames.add(entryName);
			}
		}
	} catch (IOException e) {
		throw new RuntimeException(e);
	}

	if (classNames.size() > 0) {
		for (String className : classNames) {
			try {
				Class<?> theClass = classLoader.loadClass(className);
				if (clazz.isAssignableFrom(theClass) && !theClass.equals(clazz)) {
					classList.add(theClass);
				}
			} catch (ClassNotFoundException e) {
				throw new RuntimeException(e);
			}
		}
	}
	return classList;
}

    还需要做一些准备:

    1,定义一个接口,外部去实现:

import java.util.Map;

public interface IService {
    String name();

    Object process(Map<String, Object> params);
}

    2、三方实现:


import com.example.service.IService;
im
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffy5459

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值