Patrones de Proxy Dinámico en Java

Conceptos del Patrón Proxy

El patrón proxy permite controlar el acceso a un objeto mediante un intermediario, añadiendo funcionalidades sin alterar el objeto principal. Se compone de tres elementos:

  • Sujeto: Define la interfaz común para el objeto real y su proxy
  • Sujeto Real: Implementa la lógica principal de negocio
  • Proxy: Actúa como intermediario y añade funcionalidades adicoinales

Proxy Estático

Ejemplo básico con interfaz común:

public interface Movible {
    void mover();
}

public class Perro implements Movible {
    @Override
    public void mover() {
        System.out.println("Perro moviéndose...");
        try {
            Thread.sleep(new Random().nextInt(1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Proxy para medición de tiempo:

public class ProxyTiempo implements Movible {
    private final Movible objetivo;
    
    public ProxyTiempo(Movible objetivo) {
        this.objetivo = objetivo;
    }
    
    @Override
    public void mover() {
        long inicio = System.currentTimeMillis();
        objetivo.mover();
        long fin = System.currentTimeMillis();
        System.out.println("Tiempo de movimiento: " + (fin - inicio) + "ms");
    }
}

Limitaciones

  • Requiere múltiples proxies para diferentes clases
  • Duplicación de lógica en métodos múltiples

Proxy Dinámico con JDK

Requiere interfaces y manejo mediante invocation handlers:

public interface Operaciones {
    void guardar();
    void borrar();
}

public class ProxyDinamico implements InvocationHandler {
    private final Object objetivo;
    
    public ProxyDinamico(Object objetivo) {
        this.objetivo = objetivo;
    }
    
    @Override
    public Object invoke(Object proxy, Method metodo, Object[] args) throws Throwable {
        System.out.println("Inicio: " + new Date());
        Object resultado = metodo.invoke(objetivo, args);
        System.out.println("Fin: " + new Date());
        return resultado;
    }
}

Implementación

Operaciones instancia = (Operaciones) Proxy.newProxyInstance(
    OperacionesImpl.class.getClassLoader(),
    new Class[]{Operaciones.class},
    new ProxyDinamico(new OperacionesImpl())
);
instancia.guardar();

Proxy con CGLIB

Alternativa para clases sin interfaces mediante herencia:

public class InterceptorLog implements MethodInterceptor {
    @Override
    public Object intercept(Object objeto, Method metodo, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Inicio: " + new Date());
        Object resultado = proxy.invokeSuper(objeto, args);
        System.out.println("Fin: " + new Date());
        return resultado;
    }
}

public class Cliente {
    public static void main(String[] args) {
        Enhancer mejorador = new Enhancer();
        mejorador.setSuperclass(Producto.class);
        mejorador.setCallback(new InterceptorLog());
        Producto proxy = (Producto) mejorador.create();
        proxy.guardar();
    }
}

Comparativa

JDK CGLIB
Requiere interfaces Funciona con clases concretas
Generación más rápida Mayor overhead inicial
No requiere dependencias externas Necesita biblioteca CGLIB
Limitado a métodos de interfaz Proxy de clases completas

Etiquetas: java ProxyDinámico JDK CGLib PatronesDiseño

Publicado el 8-16 20:52