Ejemplo: carga de una clase Java en tiempo de ejecución

E

Java no es el lenguaje más dinámico que existe, pero con una planificación cuidadosa y flexibilidad puede hacer que sus programas sean un poco más dinámicos cargando clases en tiempo de ejecución.

Esto puede ser útil cuando desee hacer que su aplicación sea más extensible y permitir que ciertos módulos dentro de ella sean reemplazados simplemente colocando un jar que implementa una interfaz en un directorio.

O puede cargar escrito por el usuario plugins en tiempo de ejecución. Por ejemplo, esto podría ser útil para agregar funcionalidad a una aplicación web. Colocar un plugin podría permitirle cambiar la forma en que se realiza la autenticación de usuario o podría agregar un mejor registro.

El código

Aquí hay un código que lo ayudará a cargar dinámicamente una nueva clase dada la ruta a su archivo jar.

import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

public class ExtensionLoader<C> {

  public C LoadClass(String directory, String classpath, Class<C> parentClass) throws ClassNotFoundException {
    File pluginsDir = new File(System.getProperty("user.dir") + directory);
    for (File jar : pluginsDir.listFiles()) {
      try {
        ClassLoader loader = URLClassLoader.newInstance(
            new URL[] { jar.toURL() },
            getClass().getClassLoader()
        );
        Class<?> clazz = Class.forName(classpath, true, loader);
        Class<? extends C> newClass = clazz.asSubclass(parentClass);
        // Apparently its bad to use Class.newInstance, so we use 
        // newClass.getConstructor() instead
        Constructor<? extends C> constructor = newClass.getConstructor();
        return constructor.newInstance();
        
      } catch (ClassNotFoundException e) {
        // There might be multiple JARs in the directory,
        // so keep looking
        continue;
      } catch (MalformedURLException e) {
        e.printStackTrace();
      } catch (NoSuchMethodException e) {
        e.printStackTrace();
      } catch (InvocationTargetException e) {
        e.printStackTrace();
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      } catch (InstantiationException e) {
        e.printStackTrace();
      }
    }
    throw new ClassNotFoundException("Class " + classpath
        + " wasn't found in directory " + System.getProperty("user.dir") + directory);
  }
}

Usando el código:

ExtensionLoader<MyPlugin> loader = new ExtensionLoader<MyPlugin>();
somePlugin = loader.LoadClass("path/to/jar/file", "com.example.pluginXYZ", MyPlugin.class);

Algunas notas

Sin duda, existen mejores formas de hacer que una aplicación sea extensible (OSGi, Portlets, JPF, etc.), pero a veces solo necesitas algo simple como esto.

Tenga en cuenta que ExtensionLoader solo llama a constructores sin argumentos (clases tipo bean). Podría ser más beneficioso devolver un Constructor<? extends C> class y llámelo con los argumentos apropiados. Si este es el caso, asegúrese de cargar el constructor correcto desde el newClass.getConstructor() método.

ADVERTENCIA: No se realizan controles de seguridad en este código, ¡así que asegúrese de confiar en las clases que está cargando!

.

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias para su correcto funcionamiento. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad