我如何可以加载Java类的数据库?

问题描述:

像下面的源代码:我如何可以加载Java类的数据库?

package util.abc; 
public class Test{ 
    public String out(){ 
     return "Hello World!"; 
    } 
} 

我可以使用:

Class c = Class.forName("util.abc.Test"); 

得到这个类,但我必须把这个源文件(Test.java)CLASSPATH中/util/abc/

我想动态负载这个类从数据库(源代码存储为string,或binary

这可能吗?

感谢帮助:)

+0

所以你想要在数据库中存储源代码(不是编译后的类),在运行中编译它,然后加载它? – justkt 2011-03-16 18:06:09

+0

@justkt是的,我可以做到吗?谢谢:) – Koerr 2011-03-16 18:16:34

假设你已经编译的类,你可以创建一个DatabaseClassLoader,从数据库加载类。

public class DatabaseClassLoader extends ClassLoader { 

    public DatabaseClassLoader(ClassLoader parent, ... /* connection to database */) { 
     super(parent); 
     // store the connection 
    } 

    public Class findClass(String name) { 
     byte[] data = loadDataFromDatabase(name); 
     return defineClass(name, data, 0, data.length); 
    } 
    private byte[] loadDataFromDatabase(String name) { 
     // this is your job. 
    } 
} 

如果数据库只包含源代码,你必须先编译它 - 看看Java编译器API如何做到这一点没有任何文件。

注意的是,加载这样会活下去,只要类加载器是活的,所以你需要一个新的类加载器能够在重载的情况下更改类的类。另外,如果你想通过反射之外的其他方式与类进行交互,你最好让它实现一些接口(它本身在你的类路径中),并让应用程序类加载器成为数据库的父类类加载器。

啊,以及如何装入:

Class<?> c = Class.forName("util.abc.Test", myClassLoader); 

或直接

Class<?> c = myClassLoader.loadClass("util.abc.Test"); 

这里是为您创建界面的对象(任何接口,其实)的方法:

public <X> X getImplementingObject(Class<X> interfaceClass, String className) 
    throws ClassNotFoundException, IllegalAccessException, InstantiationException 
{ 
    ClassLoader loader = new DatabaseClassLoader(interfaceClass.getClassLoader(), ...); 
    Class<?> cl = loader.loadClass(className); 
    Class<? extends X> c = cl.asSubclass(interfaceClass); 
    return c.newInstance(); 
} 

(它需要CL屁股有一个无参数的构造函数不抛出任何异常,当然,(如果是的话,你会得到这个异常抛出,太)。

这会为每个这样的类创建一个新的ClassLoader,因此它们只能通过接口(或反射)相互协作。

对于实时编译,您应该查看Java编译器API,如dcn的答案中所述。但我认为这将是更好地做这使类到数据库不是谁拉出来的面一侧的编译。

+0

谢谢,可以根据我的例子,代码完成? – Koerr 2011-03-16 18:19:40

+0

@Zenofo:对不起,我不明白你的问题。您想做什么? – 2011-03-16 18:21:44

+0

我有一个接口,我想通过这个接口实现多个类的使用,所以,为了便于扩展,我希望将implements类的源存储在数据库中。 – Koerr 2011-03-16 18:39:49

如果要将源代码存储在DB中,可以使用Java 6 Compiler API在运行时对其进行编译。例如,请参阅here

为了在运行时加载类,如果可以使用URL指定字节码的位置,则可以使用URLClassLoader,或者使用ClassLoader.defineClass并将字节码作为字节数组提供。

无论哪种方式,你应该注意,为了使用你的动态加载的类,它应该实现一个在编译时已知的接口。