自定义ClassLoader,如何使用? [英] Custom ClassLoader, how to use?
问题描述
我正在尝试使用自定义类加载器来加载应用程序所需的所有依赖项.我已在以下网站上实现了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;
}
推荐答案
当您使用new
,import
关键字时,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.jar
和spring-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:
-
BootStrap
类和Target
类不属于同一个jar文件. -
target.jar
未存储在CLASSPATH
路径中.
- The
BootStrap
class andTarget
class don't belong to a same jar file. - The
target.jar
is not stored inCLASSPATH
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屋!