Java 双亲委派问题&解决实战
Posted master-dragon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 双亲委派问题&解决实战相关的知识,希望对你有一定的参考价值。
接上一篇: Java 双亲委派问题&解决实战(一),讨论依赖中的类加载问题
设想如下场景
- demo1 的1.0;2.0;3.0 三个版本分别被其它模块依赖;如果业务bundle-main要正常运行依赖结果,这显然要冲突
项目工程如下:
经过上一篇文章,显然只要我们自定义类加载器,每个模块类正确加载对应版本的即可,代码如下
package com.dq.bundle.main;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
/**
* @Author mubi
* @Date 2021/3/13 10:47
*/
public class Main
public static void main(String[] args) throws
MalformedURLException,
ClassNotFoundException,
IllegalAccessException,
InstantiationException,
NoSuchMethodException,
InvocationTargetException
Main m = new Main();
String hello1Path = "/Users/mubi/IdeaProjects/bundle/demo2/src/main/lib/demo1-1.0-SNAPSHOT.jar";
String hello2Path = "/Users/mubi/IdeaProjects/bundle/demo3/src/main/lib/demo1-2.0-SNAPSHOT.jar";
String hello3Path = "/Users/mubi/IdeaProjects/bundle/demo1/target/demo1-3.0-SNAPSHOT.jar";
URLClassLoader helloClassLoader1 = new URLClassLoader(m.convert2URLArray(hello1Path));
URLClassLoader helloClassLoader2 = new URLClassLoader(m.convert2URLArray(hello2Path));
URLClassLoader helloClassLoader3 = new URLClassLoader(m.convert2URLArray(hello3Path));
/**
* 正常加载Hello类 版本3
*/
Class<?> helloClass3 = helloClassLoader3.loadClass("com.dq.bundle.demo1.Hello");
Object helloInstance = helloClass3.newInstance();
Method sayMethod = helloClass3.getMethod("say", String.class);
sayMethod.invoke(helloInstance, "world");
// User类使用 Hello 版本1
String userPath = "/Users/mubi/IdeaProjects/bundle/demo2/target/demo2-3.0-SNAPSHOT.jar";
SelfClassLoader userLoader = new SelfClassLoader(m.convert2URLArray(userPath),
helloClassLoader1);
// Teacher类使用 Hello 版本2
String teacherPath = "/Users/mubi/IdeaProjects/bundle/demo3/target/demo3-3.0-SNAPSHOT.jar";
SelfClassLoader teacherLoader = new SelfClassLoader(m.convert2URLArray(teacherPath),
helloClassLoader2);
/**
* 正常加载User类, 并使用传递过来的 helloClassLoader1 正常加载Hello类
*/
Class<?> helloClass1 = helloClassLoader1.loadClass("com.dq.bundle.demo1.Hello");
Object helloInstance1 = helloClass1.newInstance();
Class<?> userClass = userLoader.loadClass("com.dq.bundle.demo2.User");
Object userInstance = userClass.newInstance();
Method welcomeMethod = userClass.getMethod("welcome", helloClass1);
welcomeMethod.invoke(userInstance, helloInstance1);
/**
* 正常加载Teacher类,并使用传递过来的 helloClassLoader2 正常加载Hello类
*/
Class<?> helloClass2 = helloClassLoader2.loadClass("com.dq.bundle.demo1.Hello");
Object helloInstance2 = helloClass2.newInstance();
Class<?> teacherClass = teacherLoader.loadClass("com.dq.bundle.demo3.Teacher");
Object teacherInstance = teacherClass.newInstance();
Method welcomeTeacherMethod = teacherClass.getMethod("welcome", helloClass2);
welcomeTeacherMethod.invoke(teacherInstance, helloInstance2);
/**
* 自定义类加载器,可以传入其它类加载器
*/
static class SelfClassLoader extends URLClassLoader
private ClassLoader parentClassLoader;
public SelfClassLoader(URL[] urls, ClassLoader classLoader)
super(urls);
this.parentClassLoader = classLoader;
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException
Class<?> clazz = loadFromParent(name);
if (clazz != null)
return clazz;
return super.loadClass(name);
public Class<?> loadFromParent(String name)
// 从当前classLoader加载
Class<?> loadClass = super.findLoadedClass(name);
try
if (loadClass == null)
// 用父加载加载,这里是自己传入的类加载器
loadClass = this.parentClassLoader.loadClass(name);
catch (ClassNotFoundException e)
// e.printStackTrace();
return loadClass;
private URL[] convert2URLArray(String filePath) throws MalformedURLException
File f = new File(filePath);
URL[] urls = new URL[1];
urls[0] = f.toURI().toURL();
return urls;
正常运行如下
附:多版本类加载问题
如上可以正常运行3个demo1版本,本质原因:类加载器
+ 类全限定名
才是确定一个类的;我们都是com.dq.bundle.demo1.Hello
这个类限定名,但是我们有3个不同的类加载器,这就让我们能够在一个工程中同时使用3个版本的demo1
String hello1Path = "/Users/mubi/IdeaProjects/bundle/demo2/src/main/lib/demo1-1.0-SNAPSHOT.jar";
String hello2Path = "/Users/mubi/IdeaProjects/bundle/demo3/src/main/lib/demo1-2.0-SNAPSHOT.jar";
String hello3Path = "/Users/mubi/IdeaProjects/bundle/demo1/target/demo1-3.0-SNAPSHOT.jar";
URLClassLoader helloClassLoader1 = new URLClassLoader(m.convert2URLArray(hello1Path));
URLClassLoader helloClassLoader2 = new URLClassLoader(m.convert2URLArray(hello2Path));
URLClassLoader helloClassLoader3 = new URLClassLoader(m.convert2URLArray(hello3Path));
而所谓的类加载则是自己重写了loadClass
方法实现的。
以上是关于Java 双亲委派问题&解决实战的主要内容,如果未能解决你的问题,请参考以下文章
Java双亲委派模型:为什么要双亲委派?如何打破它?破在哪里?
Java双亲委派模型:为什么要双亲委派?如何打破它?破在哪里?
面试必备:什么时候要打破双亲委派机制?什么是双亲委派? (图解+秒懂+史上最全)