Sobes.tech
Middle

Welke soorten proxy-servers kent u?

sobes.tech AI

Antwoord van AI

In Java, er zijn de volgende soorten proxies:

  • Statische (Static Proxy): Wordt geïmplementeerd door het maken van een aparte wrapper-klasse die een verwijzing bevat naar het echte object en methoden aanroept, terwijl hij zijn eigen logica toevoegt (bijvoorbeeld logging, authenticatie).

    // Interface
    interface Service {
        void doSomething();
    }
    
    // Echte object
    class RealService implements Service {
        @Override
        public void doSomething() {
            System.out.println("Echte actie");
        }
    }
    
    // Statische proxy
    class StaticServiceProxy implements Service {
        private final Service realService;
    
        public StaticServiceProxy(Service realService) {
            this.realService = realService;
        }
    
        @Override
        public void doSomething() {
            System.out.println("Voor het aanroepen van de echte methode");
            realService.doSomething();
            System.out.println("Na het aanroepen van de echte methode");
        }
    }
    
  • Dynamische (Dynamic Proxy): Wordt tijdens runtime gemaakt met behulp van Reflection API en vereist dat het geproxyde object ten minste één interface implementeert. Hiermee kunnen proxies voor meerdere klassen die één interface implementeren worden gegenereerd zonder voor elke klasse een aparte proxy te maken.

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    // Handler voor dynamische proxies
    class DynamicServiceInvocationHandler implements InvocationHandler {
        private final Object target; // Doelobject
    
        public DynamicServiceInvocationHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Voor het aanroepen van methode " + method.getName());
            Object result = method.invoke(target, args); // Aanroepen van de methode op het doelobject
            System.out.println("Na het aanroepen van methode " + method.getName());
            return result;
        }
    }
    
    // Voorbeeld van gebruik (voor de interface Service uit het statische proxy-voorbeeld)
    // Service realService = new RealService();
    // Service proxy = (Service) Proxy.newProxyInstance(
    //     realService.getClass().getClassLoader(),
    //     realService.getClass().getInterfaces(),
    //     new DynamicServiceInvocationHandler(realService));
    // proxy.doSomething();
    
  • CGLIB Proxy: Gebaseerd op bytecode-generatie en vereist geen interface-implementatie. Kan specifieke klassen proxyen (als ze niet final zijn en methoden niet final). Het is in sommige scenario's efficiënter dan standaard dynamische proxies.

    // Voorbeeld van CGLIB gebruik (vereist externe bibliotheek)
    // public class RealService {
    //     public void doSomething() {
    //         System.out.println("Echte actie");
    //     }
    // }
    
    // 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("Voor het aanroepen van methode " + method.getName());
    //         Object result = proxy.invokeSuper(obj, args); // Aanroepen van de superklasse methode
    //         System.out.println("Na het aanroepen van methode " + method.getName());
    //         return result;
    //     }
    // }
    
    // // Gebruik voorbeeld:
    // // Enhancer enhancer = new Enhancer();
    // // enhancer.setSuperclass(RealService.class);
    // // enhancer.setCallback(new CglibServiceInterceptor());
    // // RealService proxy = (RealService) enhancer.create();
    // // proxy.doSomething();
    

Belangrijkste verschillen:

Proxytipo Vereist Interface Generatie Flexibiliteit Prestaties Toepassing
Statisch Ja Handmatig Laag (voor elke klasse) Hoog Eenvoudige gevallen, structuur bekend
Dynamisch Ja Tijdens runtime Hoog (voor interfaces) Gemiddeld Algemene logica voor interfaces, AOP
CGLIB Nee Tijdens runtime Hoog (voor klassen) Hoog AOP, proxying van klassen zonder interfaces