Sobes.tech
Middle

Que tipos de servidores proxy conhece?

sobes.tech IA

Resposta da IA

Em Java, existem os seguintes tipos de proxies:

  • Proxy Estático (Static Proxy): Implementa-se criando uma classe envolvente separada que contém uma referência ao objeto real e delega chamadas aos seus métodos, adicionando a sua própria lógica (por exemplo, registo, autorização).

    // Interface
    interface Service {
        void doSomething();
    }
    
    // Objeto real
    class RealService implements Service {
        @Override
        public void doSomething() {
            System.out.println("Ação 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 chamar o método real");
            realService.doSomething();
            System.out.println("Depois de chamar o método real");
        }
    }
    
  • Proxy Dinâmico (Dynamic Proxy): Criados em tempo de execução usando Reflection API e requerem que o objeto proxy implemente pelo menos uma interface. Permitem gerar proxies para múltiplas classes que implementam uma mesma interface, sem criar uma classe separada para cada uma.

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    // Manipulador de chamadas para proxy dinâmico
    class DynamicServiceInvocationHandler implements InvocationHandler {
        private final Object target; // Objeto alvo
    
        public DynamicServiceInvocationHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Antes de chamar o método " + method.getName());
            Object result = method.invoke(target, args); // Chamada do método do objeto alvo
            System.out.println("Depois de chamar o método " + method.getName());
            return result;
        }
    }
    
    // Exemplo de uso (para a interface Service do 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: Baseado na geração de bytecode e não requer implementação de uma interface. Pode proxyar classes concretas (se não forem finais e seus métodos não forem finais). É mais eficiente do que o proxy dinâmico padrão em certos cenários.

    // Exemplo de uso do CGLIB (requer biblioteca externa)
    // public class RealService {
    //     public void doSomething() {
    //         System.out.println("Ação 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 chamar o método " + method.getName());
    //         Object result = proxy.invokeSuper(obj, args); // Chamada do método da superclasse (objeto original)
    //         System.out.println("Depois de chamar o método " + method.getName());
    //         return result;
    //     }
    // }
    
    // // Exemplo de uso:
    // // Enhancer enhancer = new Enhancer();
    // // enhancer.setSuperclass(RealService.class);
    // // enhancer.setCallback(new CglibServiceInterceptor());
    // // RealService proxy = (RealService) enhancer.create();
    // // proxy.doSomething();
    

Principais diferenças:

Tipo de Proxy Requer Interface Geração Flexibilidade Performance Aplicação
Estático Sim Manual Baixa (para cada classe) Alta Casos simples, estrutura conhecida
Dinâmico Sim Em tempo de execução Alta (para interfaces) Média Lógica comum para interfaces, AOP
CGLIB Não Em tempo de execução Alta (para classes) Alta AOP, proxy de classes sem interfaces