当Web应用程序以Tomcat
加载时,它是由特定的类加载器加载的,对吗?
我假设此Web应用程序使用的所有库(在WEB-INF\lib
下)都由同一类加载器加载吗?
在这种情况下,有没有办法在其他类加载器下加载库而不会出现任何问题?
我想这样做的原因是因为Axis
使用绑定到类加载器的一些配置属性,并且希望使用不同的属性进行请求,从而使用不同的类加载器。
这可能吗?
最佳答案
如果要在运行时以编程方式加载类,则可以使用URLClassLoader,但要正确完成它可能非常棘手。您将执行以下操作:
URL[] urls = new URL[] {
/* URL to your axis jar */,
/* other URLs you need */
};
URLClassLoader classLoader = new URLClassLoader(urls, getClass().getClassLoader());
Class<...> axisClass = classLoader.findClass(/* fully qualified name */);
然后,您应该能够创建此类的新实例并使用它。
编辑:这是一个更具体的示例,尽管不使用Axis,因为它太难设置了。我创建了一个包含以下类的JAR文件:
public class Hello {
public Hello(String config) {
}
public String getMessage() {
return "Hello World";
}
}
我已将此jar文件复制到测试项目的源文件夹中,因此可以使用
UrlClassloaderTest.class.getResource("hello.jar")
找到它。在Web应用程序中,您可能应该将其放入WebContent / WEB-INF(或类似内容)中,并使用javax.servlet.ServletContext.getRealPath("WEB-INF/hello.jar")
方法进行查找。然后,我可以使用URLClassLoader和反射来访问Hello类:public class UrlClassloaderTest {
public static void main(String[] args) throws Exception {
URL jarUrl = UrlClassloaderTest.class.getResource("hello.jar");
URLClassLoader cl = new URLClassLoader(new URL[] { jarUrl }, UrlClassloaderTest.class.getClassLoader());
Class helloClass = cl.loadClass("test.Hello");
Constructor constructor = helloClass.getConstructor(String.class);
Object helloObject = constructor.newInstance("some configuration");
Method messageMethod = helloClass.getMethod("getMessage");
String message = (String) messageMethod.invoke(helloObject);
System.out.println(message);
}
}
请注意,我不能在此处将Hello用作类型,因为它不在应用程序的类路径中,因此
UrlClassLoaderTest
类的类加载器不知道它!