Java: carica l'implementazione dell'interfaccia definita dall'utente (dal file di configurazione)
Devo consentire a un utente di specificare l'implementazione di un'interfaccia in fase di runtime tramite un file di configurazione, simile a questa domanda: Specificare quale implementazione dell'interfaccia Java utilizzare nell'argomento della riga di comando
Tuttavia, la mia situazione è diversa in quanto le implementazioni non sono note in fase di compilazione, quindi dovrò usare reflection per istanziare la classe. La mia domanda è :.. come strutturo la mia applicazione in modo tale che la mia classe possa vedere la nuova implementazione .jar, affinch possa caricare la classe quando chiamo:
Class.forName(fileObject.getClassName()).newInstance()
?
1 answers
Il commento è corretto; fino a quando il .il file jar è nel tuo classpath, puoi caricare la classe.
Ho usato qualcosa di simile in passato:
public static MyInterface loadMyInterface( String userClass ) throws Exception
{
// Load the defined class by the user if it implements our interface
if ( MyInterface.class.isAssignableFrom( Class.forName( userClass ) ) )
{
return (MyInterface) Class.forName( userClass ).newInstance();
}
throw new Exception("Class "+userClass+" does not implement "+MyInterface.class.getName() );
}
Dove String userClass
era il nome di classe definito dall'utente da un file di configurazione.
MODIFICA
A pensarci bene, è anche possibile caricare la classe che l'utente specifica in fase di runtime (ad esempio, dopo aver caricato una nuova classe) usando qualcosa del genere:
public static void addToClassPath(String jarFile) throws IOException
{
URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class loaderClass = URLClassLoader.class;
try {
Method method = loaderClass.getDeclaredMethod("addURL", new Class[]{URL.class});
method.setAccessible(true);
method.invoke(classLoader, new Object[]{ new File(jarFile).toURL() });
} catch (Throwable t) {
t.printStackTrace();
throw new IOException( t );
}
}
Ricordo di aver trovato l'invocazione addURL()
usando la riflessione da qualche parte qui su SO (ovviamente).