自定义ClassLoader的方式很多,简单的就是直接实现java.lang.ClassLoader类,重写findClass()loadClass()方法。
java.lang.ClassLoader是一个抽象类,
loadClass() - 其定义了双亲委派模型的模板方法loadClass(String,boolean),我们如果要打破双亲委派模型的话就可以直接重写该方法。
findClass() - 是作为loadClass(String,boolean)方法中的钩子方法,在父加载器找不到指定类时,会回调本类findClass()方法。

自定义类加载器
  1. public class MyClassLoader extends ClassLoader {
  2. // 加载外部自定路径
  3. private String dir;
  4. public MyClassLoader(ClassLoader parent, String dir) {
  5. super(parent);
  6. this.dir = dir;
  7. }
  8. @Override
  9. protected Class<?> findClass(String name) throws ClassNotFoundException {
  10. String path = name.replaceAll("\\.", "/") + ".class";
  11. try {
  12. path = dir + "/" + path;
  13. path = path.replaceAll("/+", "/");
  14. FileInputStream fis = new FileInputStream(path);
  15. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  16. int b;
  17. while ((b = fis.read()) != -1) {
  18. bos.write(b);
  19. }
  20. byte[] bytes = bos.toByteArray();
  21. // 定义内存数据结构等,该方法是final方法
  22. return defineClass(name, bytes, 0, bytes.length);
  23. } catch (Exception e) {
  24. e.printStackTrace();
  25. throw new ClassNotFoundException(e.getMessage());
  26. }
  27. }
  28. }

demo:

  1. public class ClassLoaderDemo {
  2. public static void main(String[] args) throws Exception {
  3. MyClassLoader classLoader = new MyClassLoader(ClassLoaderDemo.class.getClassLoader(), "d:/tmp/");
  4. Class<?> clazz = classLoader.loadClass("com.ext.Demo");
  5. clazz.newInstance();
  6. }
  7. }

在D盘的tmp目录下存放对应的类
image.png
执行时会加载到外部的Demo.class