我正在开发一个网络应用程序。
- Web 应用程序动态生成 Java 类。例如它生成类
com.people.Customer.java
- 在我的代码中,我动态编译它以获取 com.people.Customer.class 并存储在某个目录中
repository/com/people/Customer.class
它不在我的应用程序服务器的类路径上。我的应用程序服务器(我正在使用 WebSphere Application Server/Apache Tomcat 等)从WEB-INF/classes
目录。类加载器将使用它来加载类。
- 编译后,我需要加载此类,以便其他类在创建后可以使用它来访问它。
- 当我使用
Thread.currentThread().getContextClassLoader().loadClass(com.people.Customer)
显然,类加载器无法加载该类,因为它不在类路径上(不在WEB-INF/classes
)。由于类似的原因,getResource(..)
or getResourceAsStream(..)
也不起作用。
我需要一种方法:
读课文Customer.class
也许作为流(或任何其他方式)然后加载它。以下是限制条件:
- 我无法将存储库文件夹添加到
WEB-INF/classes
folder.
- 我无法创建新的自定义类加载器。如果我创建一个新的类加载器并加载该类,则其父类加载器将无法访问该类。
有什么办法可以实现这一点吗?
如果不是这样,在最糟糕的情况下,是否有一种方法可以使用 Web 应用程序的自定义类加载器覆盖默认类加载器,应使用相同的类加载器在 Web 应用程序的整个生命周期中加载应用程序。
感谢任何解决方案:)
你需要一个自定义的类加载器来做到这一点,并且在这个类加载器中你需要重新定义一个方法findClass(String name)
一个例子:
public class CustomClassLoader extends ClassLoader {
final String basePath = "/your/base/path/to/directory/named/repository/";
@Override
protected Class<?> findClass(final String name) throws ClassNotFoundException {
String fullName = name.replace('.', '/');
fullName += ".class";
String path = basePath + fullName ;
try {
FileInputStream fis = new FileInputStream(path);
byte[] data = new byte[fis.available()];
fis.read(data);
Class<?> res = defineClass(name, data, 0, data.length);
fis.close();
return res;
} catch(Exception e) {
return super.findClass(name);
}
}
}
然后,您将从自定义位置加载类。例如:
Class<?> clazz = Class.forName("my.pretty.Clazz", true, new CustomClassLoader());
Object obj = clazz.newInstance();
这样做,你告诉 JVM 该类名为my.pretty.Clazz
应该由您的自定义类加载器加载,它知道how and 从哪里来加载您的自定义类。
它解析完整的类名(例如my.pretty.Clazz
)到文件名(在我们的例子中:/your/base/path/to/directory/named/repository/my/pretty/Clazz.class
),然后将获得的资源作为字节数组加载,最后将该数组转换为Class
实例。
此示例非常简单,演示了有关如何在您的情况下加载自定义类的通用技术。
我建议你阅读一些关于类加载的文章,例如this one http://www.javaworld.com/jw-10-1996/jw-10-indepth.html.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)