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()

?

Author: Community, 2015-08-10

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).

 2
Author: mvreijn, 2015-08-10 19:28:32