自定义ClassLoader,如何使用?

Custom ClassLoader, how to use?

我正在尝试使用自定义 class 加载程序来加载应用程序所需的所有依赖项。我已经在网站后实施了 customerClassLoader:https://www.javacodegeeks.com/2013/03/java-handmade-classloader-isolation.html

但是,我不明白如何告诉我的应用程序在需要时使用自定义 classLoader。

例如:比方说,我有一种方法可以像下面这样发出 http 请求。我如何告诉应用程序使用自定义 classLoader 来加载所需的 jar?

private HttpResponse get() {
    HttpClient client = HttpClientBuilder.create().build();
    HttpGet request = new HttpGet(url);
    HttpResponse response = client.execute(request);
    return response;
}

您可以执行以下操作;

Thread.currentThread().setContextClassLoader(new MyCustomClassLoader());

Java 隐式使用 ClassLoader 当你使用 new, import 关键字时,jvm 将使用当前 class 的 classloader 来加载依赖的 classes,因此您可以使用自定义 classloader 通过使用 classloader.loadclassbootstrap 只是 运行 一个属于您的目标 class 实例的方法。下面是一个例子。

有一个 class Target 依赖于 class DateFormatter 包含在 spring-context 中,并且有一个名为 start.

import org.springframework.format.datetime.DateFormatter;

public class Target {

private static DateFormatter dateFormatter;

public void start(){
    System.out.println(this.getClass().getClassLoader());
    dateFormatter=new DateFormatter();
    System.out.println(dateFormatter);
    }
}

接下来我们将上面的代码编译打包成一个名为target.jar的jar,存放在D:\test\target.jar.

接下来,我们在另一个 jar 中声明一个 class BootStrap,它将调用 Target 实例的方法 startBootStrap class 将通过相同的 classloader 动态加载 target.jarspring-context jar 文件,这是一个 URLClassLoader 实例。因此,Target 实例中的方法 start 可以访问 spring-context.

中定义的 DateFormatter class
public class BootStrap {


public static void main(String[] args) throws Exception{
    URL url = new URL("http://maven.aliyun.com/nexus/content/groups/public/org/springframework/spring-context/4.3.1.RELEASE/spring-context-4.3.1.RELEASE.jar?spm=0.0.0.0.kG1Pdw&file=spring-context-4.3.1.RELEASE.jar");
    URL url2= (new File("D:\test\target.jar").toURI().toURL());
    URLClassLoader classLoader = new URLClassLoader(new URL[]{url,url2});
    Class<?> clz = classLoader.loadClass("com.zhuyiren.Target");
    Object main = clz.newInstance();
    Method test = clz.getMethod("start");
    test.invoke(main);
    }
}

最后,运行 BootStrap 主要方法。有两点很重要:

  1. BootStrapclass和Targetclass不属于同一个jar文件。
  2. target.jar 未存储在 CLASSPATH 路径中。

这两点可以保证AppClassLoader找不到和加载Target class。由于 class 加载器的机制,jvm 将使用自定义加载 Target。当然,你可以通过将 URLClassLoader classLoader = new URLClassLoader(new URL[]{url,url2}); 更改为 URLClassLoader classLoader = new URLClassLoader(new URL[]{url, url2}, ClassLoader.getSystemClassLoader().getParent());

来保证

我们可以看到结果:

java.net.URLClassLoader@e9e54c2
org.springframework.format.datetime.DateFormatter@4dd8dc3

这意味着我们可以成功访问spring-context jar文件中定义的DateFormatter实例,而spring-context没有存储在CLASSPATH中,但我们是使用自定义类加载器加载和使用它。