一、加载简单java对象
编写一个类,不依赖任何其他jar,如下
package cc.eslink.bigscreen.controller.config; /** * @Author : wangbin * @Date : 2022/1/21 11:29 * @Description: */ public class User { private String name; public User() { System.out.println("create User!!!"); } public void setName(String name){ this.name=name; } public String getName(){ return this.name; } }
打成jar包,切记,一定打成原生jar包,不是胖jar
/** * 经过一天的尝试,终于把类加载跑通了,之前失败N次的原因也找到了 * 说来让人心酸,就是因为之前生成的胖jar包跟原生jar包格式不同 * 使用类加载就要使用标准jar * @param args * @throws ClassNotFoundException * @throws IllegalAccessException * @throws InstantiationException * @throws IOException */ public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, IOException { File file = new File("D:\\tlpi\\jar\\bigscreen-standard.jar"); String className = "cc.eslink.bigscreen.controller.config.User"; URL url = file.toURI().toURL(); URLClassLoader classLoader = new URLClassLoader(new URL[]{url}, Thread.currentThread().getContextClassLoader()); Class<?> aClass = classLoader.loadClass(className); aClass.newInstance(); }
输出:
create User!!!
二、加载一个依赖其他类的class
我们知道在编程中完全不依赖第三方jar基本上是不可能的,那么我们的URLClassLoader能加载这些类吗?答案是可以
我构造了一个新类,它有一些依赖的包
package com.example.api.client.config; import com.example.api.gateway.exception.CachedException; import com.example.api.gateway.exception.FailedException; import com.example.api.gateway.filter.AbstractFilter; import com.example.api.gateway.handler.HttpMessage; /** * @Author : wangbin * @Date : 2022/1/21 14:38 * @Description: */ public class ThirdFilter extends AbstractFilter { @Override public HttpMessage filter(HttpMessage request) throws FailedException, CachedException { System.out.println("I am ThirdFilter"); return null; } }
我们在加载一次
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, IOException { File file = new File("D:\\tlpi\\jar\\bigscreen-standard.jar"); String className = "com.example.api.client.config.ThirdFilter"; URL url = file.toURI().toURL(); URLClassLoader classLoader = new URLClassLoader(new URL[]{url}, Thread.currentThread().getContextClassLoader()); Class<? extends AbstractFilter> aClass =( Class<? extends AbstractFilter>) classLoader.loadClass(className); AbstractFilter filter = aClass.newInstance(); try { filter.filter(null); } catch (FailedException e) { e.printStackTrace(); } catch (CachedException e) { e.printStackTrace(); } }
输出:I am ThirdFilter
成功了,的确,但成功的很侥幸,因为ThirdFilter依赖的类恰好都在我们的JVM中,如果不在会怎样?
三、加载一个依赖其他第三方我们不知道的jar的class
为了验证我之前的猜测,我再ThirdFilter中加入一个我们现有环境中没有用过的类,代码如下:
package com.example.api.client.config; import com.example.api.gateway.exception.CachedException; import com.example.api.gateway.exception.FailedException; import com.example.api.gateway.filter.AbstractFilter; import com.example.api.gateway.handler.HttpMessage; import org.jdom.Document; /** * @Author : wangbin * @Date : 2022/1/21 14:38 * @Description:新加入org.jdom.Document */ public class ThirdFilter extends AbstractFilter { @Override public HttpMessage filter(HttpMessage request) throws FailedException, CachedException { String simpleName = Document.class.getSimpleName(); System.out.println(simpleName); System.out.println("I am ThirdFilter"); return null; } }
我们依然按照之前的方式进行类加载,不出所料,失败了
Exception in thread "main" java.lang.NoClassDefFoundError: org/jdom/Document at com.example.api.client.config.ThirdFilter.filter(ThirdFilter.java:16) at com.example.api.gateway.utils.LoadUtil.main(LoadUtil.java:54) Caused by: java.lang.ClassNotFoundException: org.jdom.Document at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 2 more
因为jvm中根本没有这个类的class,我们也没有告诉系统他的jar包在哪里。
那么是不是我告诉系统这个jar包在哪里,他就能帮我找到,我修改了类加载的方法
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, IOException { File file = new File("D:\\tlpi\\jar\\bigscreen-standard.jar"); String className = "com.example.api.client.config.ThirdFilter"; URL url = file.toURI().toURL(); File file1 = new File("D:\\tlpi\\jar\\jdom-1.1.3.jar"); URL url1 = file1.toURI().toURL(); URLClassLoader classLoader = new URLClassLoader(new URL[]{url,url1}, Thread.currentThread().getContextClassLoader()); Class<? extends AbstractFilter> aClass =( Class<? extends AbstractFilter>) classLoader.loadClass(className); AbstractFilter filter = aClass.newInstance(); try { filter.filter(null); } catch (FailedException e) { e.printStackTrace(); } catch (CachedException e) { e.printStackTrace(); } }
输出:
Document
I am ThirdFilter
成功了,证明我们的推测是正确的!