自定义ClassLoader,如何使用? [英] Custom ClassLoader, how to use?

查看:83
本文介绍了自定义ClassLoader,如何使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to use a custom class loader to load all the dependencies needed for the application. I've implemented the customerClassLoader following the site: https://www.javacodegeeks.com/2013/03/java-handmade-classloader-isolation.html

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

However, I dont understand how to tell my application to use the custom classLoader whenever needed.

例如:可以说,我有一个发出http请求的方法,如下所示.如何告诉应用程序使用自定义的classLoader加载所需的jar?

For instance: Lets say, I have a method to make http request like below. How can I tell the application to use the custom classLoader to load the required jars?

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

推荐答案

当您使用newimport关键字时,Java隐式使用ClassLoader,jvm将使用当前类的类加载器来加载相关类,因此您可以使用自定义类加载器通过使用classloader.loadclass显式加载bootstrap类,而bootstrap只是运行属于您的目标类实例的方法.下面是一个示例.

Java uses ClassLoader implicitly when you use new, import keyword, the jvm will use the current class's classloader to load the dependent classes, so you can use the custom classloader to load a bootstrap class explicitly by using classloader.loadclass, and the bootstrap just runs a method belonging to your target class instance. An example follows.

有一个类Target依赖于spring-context中包含的类DateFormatter,并且具有名为start的方法.

There is a class Target that depends on the class DateFormatter which is included in the spring-context, and has a method named 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中.

Next, we compile and package the above code as a jar named target.jar, which is stored at D:\\test\\target.jar.

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

Next, we declare a class BootStrap in another jar that will call the method start of Target instance. The BootStrap class will dynamically load the target.jar and spring-context jar files by the same classloader which is a URLClassLoader instance. Because of this, the method start in Target instance can access the DateFormatter class that is defined in 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方法.有两个重要的事情:

Finally, run the BootStrap main method. There are two important thing:

  1. BootStrap类和Target类不属于同一个jar文件.
  2. target.jar未存储在CLASSPATH路径中.
  1. The BootStrap class and Target class don't belong to a same jar file.
  2. The target.jar is not stored in CLASSPATH path.

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

These 2 point can make sure that the AppClassLoader can not find and load the Target class. Because of the mechanism of class loader, jvm will use the custom load the Target. Of course, you can guarantee it by changing the URLClassLoader classLoader = new URLClassLoader(new URL[]{url,url2}); to 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中,但是我们正在使用自定义的clasloader进行加载和使用.

That means we can access the DateFormatter instance which is defined in spring-context jar file successfully, while the spring-context is not stored in CLASSPATH, but we are using the custom clasloader to load and use it.

这篇关于自定义ClassLoader,如何使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆