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

    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!

    .

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *