在Web应用程序中动态地在类路径中动态加载类-无需使用自定义类加载器 [英] load class not in classpath dynamically in web application - without using custom classloader

查看:44
本文介绍了在Web应用程序中动态地在类路径中动态加载类-无需使用自定义类加载器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发Web应用程序.

I am developing a web application.

  1. 该Web应用程序会即时生成Java类.例如,它生成类 com.people.Customer.java
  2. 在我的代码中,我动态编译它以获取com.people.Customer.class并将其存储在某个目录中,例如 repository/com/people/Customer.class ,该目录不在我的类路径中应用程序服务器.我的应用程序服务器(我正在使用WebSphere Application Server/Apache Tomcat等)从 WEB-INF/classes 目录中选择类.类加载器将使用它来加载类.
  3. 编译后,我需要加载该类,以便使用它创建后的其他类可以访问该类.
  4. 当我使用 Thread.currentThread().getContextClassLoader().loadClass(com.people.Customer)时,显然Classloader无法加载该类,因为它不在classpath上(不是在 WEB-INF/classes 中).由于类似的原因, getResource(..) getResourceAsStream(..)也不起作用.
  1. The web application generates java classes on the fly. For example it generates class com.people.Customer.java
  2. In my code, I dynamically compile this to get com.people.Customer.class and store in some directory say repository/com/people/Customer.class which is not on the classpath of my application server.My application server(I am using WebSphere Application Server/Apache Tomcat etc) picks up the classes from the WEB-INF/classes directory. The Classloader would use this to load the classes.
  3. After compilation I need to load this class so that it becomes accessible to other classes using it after its creation.
  4. When I use Thread.currentThread().getContextClassLoader().loadClass(com.people.Customer) obviously the Classloader is not able to load the class, since its not on the classpath(not in WEB-INF/classes). Due to similar reasons, getResource(..) or getResourceAsStream(..) also does not work.

我需要一种方法:

可能以流(或任何其他方式)读取类 Customer.class ,然后加载它.以下是约束:

Read the class Customer.class maybe as a stream (or any other way would do) and then load it. Following are the constraints:

  1. 我无法将存储库文件夹添加到 WEB-INF/classes 文件夹中.
  2. 我无法创建新的自定义ClassLoader.如果我创建一个新的ClassLoader并加载了该类,则其父ClassLoader将无法访问它.

有什么办法可以做到这一点?

Is there any way of achieving this?

如果不是这样,在最坏的情况下,是否有一种方法可以使用针对Web应用程序的自定义类加载器覆盖默认类加载器,因此应在我的Web应用程序的整个生命周期中使用相同的类加载器来加载应用程序.

If not this, in the worse case, is there a way of overriding the default class loader with a custom class loader for web applications the same classloader should be used to load applications throughout entire lifecycle of my web application.

赞赏任何解决方案:)

Appreciate any solution :)

推荐答案

您需要一个自定义类加载器来执行此操作,并且在此类加载器中,您需要重新定义方法 findClass(String name)

You need a custom class loader to do this, and in this classloader you need to re-define a method 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);
        }
    }
}

然后,您将从自定义位置加载类.例如:

Then, you'll be load classes from custom location. For example:

Class<?> clazz = Class.forName("my.pretty.Clazz", true, new CustomClassLoader());
Object obj = clazz.newInstance();

这样做,您告诉JVM名为 my.pretty.Clazz 的类应由您的自定义类加载器加载,该类加载器知道如何从何处来加载您的自定义类.它将完整的类名(例如 my.pretty.Clazz )解析为文件名(在我们的示例中:/your/base/path/to/directory/named/repository/my/pretty/Clazz.class ),然后将获取的资源加载为字节数组,最后将此数组转换为 Class 实例.

Doing this, you tell JVM that class named my.pretty.Clazz should be loaded by your custom class loader, which knows how and where from to load your custom class. It resolves full class name (like my.pretty.Clazz) to file name (in our case: /your/base/path/to/directory/named/repository/my/pretty/Clazz.class), then loads obtained resource as a byte array, and finally converts this array to a Class instance.

此示例非常简单,并演示了如何根据您的情况加载自定义类的常规技术.我建议您阅读一些有关类加载的文章,例如此文章.

This example is very simple and demonstrates a general technique about how to load custom classes as in your case. I suggest you to read some articles about class loading, for example this one.

这篇关于在Web应用程序中动态地在类路径中动态加载类-无需使用自定义类加载器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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