Sobes.tech
Middle

Aké typy proxy serverov poznáte?

sobes.tech AI

Odpoveď od AI

V Jave existujú nasledujúce typy proxy:

  • Statický (Static Proxy): Implementuje sa vytvorením samostatnej triedy-obalu, ktorá obsahuje odkaz na skutočný objekt a deleguje mu volania metód, pričom pridáva vlastnú logiku (napríklad logovanie, autorizácia).

    // Rozhranie
    interface Service {
        void doSomething();
    }
    
    // Skutočný objekt
    class RealService implements Service {
        @Override
        public void doSomething() {
            System.out.println("Skutočná akcia");
        }
    }
    
    // Statický proxy
    class StaticServiceProxy implements Service {
        private final Service realService;
    
        public StaticServiceProxy(Service realService) {
            this.realService = realService;
        }
    
        @Override
        public void doSomething() {
            System.out.println("Pred volaním skutočnej metódy");
            realService.doSomething();
            System.out.println("Po volaní skutočnej metódy");
        }
    }
    
  • Dynamický (Dynamic Proxy): Vytvára sa počas behu pomocou Reflection API a vyžaduje, aby proxy-ovaný objekt implementoval aspoň jeden rozhranie. Umožňuje generovať proxy pre viacero tried implementujúcich rovnaké rozhranie, bez vytvárania samostatnej triedy pre každú.

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    // Handler pre volania pre dynamický proxy
    class DynamicServiceInvocationHandler implements InvocationHandler {
        private final Object target; // Cieľový objekt
    
        public DynamicServiceInvocationHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Pred volaním metódy " + method.getName());
            Object result = method.invoke(target, args); // Volanie metódy cieľového objektu
            System.out.println("Po volaní metódy " + method.getName());
            return result;
        }
    }
    
    // Príklad použitia (pre rozhranie Service z prí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 generovaní bajtkódu a nevyžaduje implementáciu rozhrania. Môže proxy-ovať konkrétne triedy (ak nie sú finálne a metódy nie sú finálne). Je výkonnejší ako štandardný dynamický proxy v niektorých scenároch.

    // Príklad použitia CGLIB (vyžaduje externú knižnicu)
    // public class RealService {
    //     public void doSomething() {
    //         System.out.println("Skutočná akcia");
    //     }
    // }
    
    // 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("Pred volaním metódy " + method.getName());
    //         Object result = proxy.invokeSuper(obj, args); // Volanie metódy supertriedy (originálneho objektu)
    //         System.out.println("Po volaní metódy " + method.getName());
    //         return result;
    //     }
    // }
    
    // // Príklad použitia:
    // // Enhancer enhancer = new Enhancer();
    // // enhancer.setSuperclass(RealService.class);
    // // enhancer.setCallback(new CglibServiceInterceptor());
    // // RealService proxy = (RealService) enhancer.create();
    // // proxy.doSomething();
    

Hlavné rozdiely:

Typ proxy Vyžaduje rozhranie Generovanie Flexibilita Výkon Použitie
Statický Áno Ručne Nízka (pre každý triedu) Vysoký Jednoduché prípady, keď je štruktúra známa
Dynamický Áno Počas behu Vysoká (pre rozhrania) Stredný Všeobecná logika pre rozhrania, AOP
CGLIB Nie Počas behu Vysoká (pre triedy) Vysoký AOP, proxyovanie tried bez rozhraní