3

当一个 Web 应用程序被加载时,Tomcat它是由一个特定的类加载器加载的,对吧?
我假设WEB-INF\lib此 Web 应用程序使用的所有库(在 下)都由同一个类加载器加载?
在这种情况下,有没有办法在不同的类加载器下加载库而没有任何问题?
我想这样做的原因是因为Axis使用了一些绑定到类加载器的配置属性,并且希望使用不同的属性进行请求,从而使用不同的类加载器。
这可能吗?

4

1 回答 1

3

如果您想在运行时以编程方式加载类,您可以使用 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

于 2012-11-14T06:55:10.373 回答