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 y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con tus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. 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