Sobes.tech
Middle

Jaké typy proxy serverů znáte?

sobes.tech AI

Odpověď od AI

V jazyce Java existují následující typy proxy:

  • Statický (Static Proxy): Implementuje se vytvořením samostatné třídy obalovače, která obsahuje odkaz na skutečný objekt a deleguje mu volání metod, přičemž přidává vlastní logiku (například logování, autorizace).

    // Rozhraní
    interface Service {
        void doSomething();
    }
    
    // Skutečný objekt
    class RealService implements Service {
        @Override
        public void doSomething() {
            System.out.println("Skutečná akce");
        }
    }
    
    // Statický proxy
    class StaticServiceProxy implements Service {
        private final Service realService;
    
        public StaticServiceProxy(Service realService) {
            this.realService = realService;
        }
    
        @Override
        public void doSomething() {
            System.out.println("Před voláním skutečné metody");
            realService.doSomething();
            System.out.println("Po volání skutečné metody");
        }
    }
    
  • Dynamický (Dynamic Proxy): Vytváří se za běhu pomocí Reflection API a vyžaduje, aby proxyovaný objekt implementoval alespoň jedno rozhraní. Umožňuje generovat proxy pro více tříd, které implementují stejné rozhraní, bez vytváření samostatné třídy pro každou.

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    // Zpracovatel volání
    class DynamicServiceInvocationHandler implements InvocationHandler {
        private final Object target; // Cílový objekt
    
        public DynamicServiceInvocationHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Před voláním metody " + method.getName());
            Object result = method.invoke(target, args); // Volání metody cílového objektu
            System.out.println("Po volání metody " + method.getName());
            return result;
        }
    }
    
    // Příklad použití (pro rozhraní Service z příkladu statického proxy)
    // Service realService = new RealService();
    // Service proxy = (Service) Proxy.newProxyInstance(
    //     realService.getClass().getClassLoader(),
    //     realService.getClass().getInterfaces(),
    //     new DynamicServiceInvocationHandler(realService));
    // proxy.doSomething();
    
  • CGLIB Proxy: Je založen na generování bytekódu a nevyžaduje implementaci rozhraní. Může proxyovat konkrétní třídy (pokud nejsou final a metody nejsou final). V některých scénářích je výkonnější než standardní dynamické proxy.

    // Příklad použití CGLIB (vyžaduje externí knihovnu)
    // public class RealService {
    //     public void doSomething() {
    //         System.out.println("Skutečná akce");
    //     }
    // }
    
    // 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("Před voláním metody " + method.getName());
    //         Object result = proxy.invokeSuper(obj, args); // Volání nadtřídy (originálního objektu)
    //         System.out.println("Po volání metody " + method.getName());
    //         return result;
    //     }
    // }
    
    // // Příklad použití:
    // // Enhancer enhancer = new Enhancer();
    // // enhancer.setSuperclass(RealService.class);
    // // enhancer.setCallback(new CglibServiceInterceptor());
    // // RealService proxy = (RealService) enhancer.create();
    // // proxy.doSomething();
    

Hlavní rozdíly:

Typ proxy Vyžaduje rozhraní Generace Flexibilita Výkon Použití
Statický Ano Ručně Nízká (pro každý třídu) Vysoký Jednoduché případy, struktura známá
Dynamický Ano Během běhu Vysoká (pro rozhraní) Střední Obecná logika, AOP
CGLIB Ne Během běhu Vysoká (pro třídy) Vysoký AOP, proxyování tříd bez rozhraní