Sobes.tech
Middle

¿Qué tipos de servidores proxy conoces?

sobes.tech AI

Respuesta de la IA

En Java, existen los siguientes tipos de proxies:

  • Proxy Estático (Static Proxy): Se implementa creando una clase envolvente separada que contiene una referencia al objeto real y delega llamadas a sus métodos, añadiendo su propia lógica (por ejemplo, registro, autorización).

    // Interfaz
    interface Service {
        void doSomething();
    }
    
    // Objeto real
    class RealService implements Service {
        @Override
        public void doSomething() {
            System.out.println("Acción real");
        }
    }
    
    // Proxy estático
    class StaticServiceProxy implements Service {
        private final Service realService;
    
        public StaticServiceProxy(Service realService) {
            this.realService = realService;
        }
    
        @Override
        public void doSomething() {
            System.out.println("Antes de llamar al método real");
            realService.doSomething();
            System.out.println("Después de llamar al método real");
        }
    }
    
  • Proxy Dinámico (Dynamic Proxy): Se crea en tiempo de ejecución usando Reflection API y requiere que el objeto proxy implemente al menos una interfaz. Permite generar proxies para múltiples clases que implementan una misma interfaz, sin crear una clase separada para cada una.

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    // Manejador de llamadas para proxy dinámico
    class DynamicServiceInvocationHandler implements InvocationHandler {
        private final Object target; // Objeto objetivo
    
        public DynamicServiceInvocationHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Antes de llamar al método " + method.getName());
            Object result = method.invoke(target, args); // Llamada al método del objeto objetivo
            System.out.println("Después de llamar al método " + method.getName());
            return result;
        }
    }
    
    // Ejemplo de uso (para la interfaz Service del proxy estático)
    // Service realService = new RealService();
    // Service proxy = (Service) Proxy.newProxyInstance(
    //     realService.getClass().getClassLoader(),
    //     realService.getClass().getInterfaces(),
    //     new DynamicServiceInvocationHandler(realService));
    // proxy.doSomething();
    
  • Proxy CGLIB: Basado en generación de bytecode y no requiere implementar una interfaz. Puede proxyar clases concretas (si no son finales y sus métodos no son finales). Es más eficiente que el proxy dinámico estándar en ciertos escenarios.

    // Ejemplo de uso de CGLIB (requiere librería externa)
    // public class RealService {
    //     public void doSomething() {
    //         System.out.println("Acción real");
    //     }
    // }
    
    // import net.sf.cglib.proxy.MethodInterceptor;
    // import net.sf.cglib.proxy.MethodProxy;
    // import net.sf.cglib.proxy.Enhancer;
    
    // class CglibServiceInterceptor implements MethodInterceptor {
    //     @Override
    //     public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    //         System.out.println("Antes de llamar al método " + method.getName());
    //         Object result = proxy.invokeSuper(obj, args); // Llamada al método de la superclase (objeto original)
    //         System.out.println("Después de llamar al método " + method.getName());
    //         return result;
    //     }
    // }
    
    // // Uso de ejemplo:
    // // Enhancer enhancer = new Enhancer();
    // // enhancer.setSuperclass(RealService.class);
    // // enhancer.setCallback(new CglibServiceInterceptor());
    // // RealService proxy = (RealService) enhancer.create();
    // // proxy.doSomething();
    

Diferencias principales:

Tipo de Proxy Requiere Interfaz Generación Flexibilidad Rendimiento Uso
Estático Manual Baja (para cada clase) Alto Casos simples, estructura conocida
Dinámico En tiempo de ejecución Alto (para interfaces) Medio Lógica común para interfaces, AOP
CGLIB No En tiempo de ejecución Alto (para clases) Alto AOP, proxy de clases sin interfaces