自定义ClassLoader,如何使用?

问题描述 投票:2回答:2

我试图使用自定义类加载器来加载应用程序所需的所有依赖项。我在网站后面实现了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;
}
java classloader dynamic-class-loaders
2个回答
2
投票

当您使用ClassLoadernew关键字时,Java会隐式使用import,jvm将使用当前类的类加载器来加载依赖类,因此您可以使用自定义类加载器通过使用bootstrap显式加载classloader.loadclass类,而bootstrap只运行一个方法属于您的目标类实例。一个例子如下。

有一个类Target取决于包含在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中声明一个类BootStrap,它将调用start实例的方法TargetBootStrap类将动态加载target.jarspring-context jar文件由相同的classloader,这是一个URLClassLoader实例。因此,start实例中的方法Target可以访问DateFormatter中定义的spring-context类。

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 main方法。有两件重要的事情:

  1. BootStrap类和Target类不属于同一个jar文件。
  2. target.jar没有存储在CLASSPATH路径中。

这两点可以确保AppClassLoader无法找到并加载Target类。由于类加载器的机制,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

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


0
投票

你可以做到以下几点;

Thread.currentThread().setContextClassLoader(new MyCustomClassLoader());
© www.soinside.com 2019 - 2024. All rights reserved.