이미 클래스를 컴파일 가정하면, 데이터베이스에서 클래스를로드하는 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.
}
}
먼저 컴파일해야합니다 - 모든 파일없이이 작업을 수행하는 방법에 대한 자바 컴파일러 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가 만들어 지므로 인터페이스 (또는 리플렉션)를 통해서만 서로 협업 할 수 있습니다.
직접 컴파일의 경우 dcn의 대답에서 언급 한 Java 컴파일러 API를 살펴 봐야합니다. 그러나 클래스를 데이터베이스 외부로 끌어들이는 쪽보다 데이터베이스에 클래스를 넣는 편에서 컴파일하는 것이 더 나을 것이라고 생각합니다.
그래서 컴파일 된 클래스가 아닌 소스를 데이터베이스에 저장하고 컴파일 한 다음로드하십시오. – justkt
@justkt 네, 할 수 있습니까? 감사합니다 :) – Koerr