Sobes.tech
Middle

Welche Arten von Proxy-Servern kennen Sie?

sobes.tech KI

Antwort von AI

In Java gibt es die folgenden Arten von Proxies:

  • Statischer Proxy: Wird durch Erstellen einer separaten Wrapper-Klasse implementiert, die eine Referenz auf das echte Objekt enthält und Aufrufe an dieses delegiert, wobei sie eigene Logik hinzufügt (z.B. Logging, Autorisierung).

    // Schnittstelle
    interface Service {
        void doSomething();
    }
    
    // Echtes Objekt
    class RealService implements Service {
        @Override
        public void doSomething() {
            System.out.println("Echte Aktion");
        }
    }
    
    // Statischer Proxy
    class StaticServiceProxy implements Service {
        private final Service realService;
    
        public StaticServiceProxy(Service realService) {
            this.realService = realService;
        }
    
        @Override
        public void doSomething() {
            System.out.println("Vor dem Aufruf der echten Methode");
            realService.doSomething();
            System.out.println("Nach dem Aufruf der echten Methode");
        }
    }
    
  • Dynamischer Proxy: Wird zur Laufzeit mit Reflection API erstellt und erfordert, dass das proxy-Objekt mindestens eine Schnittstelle implementiert. Ermöglicht die Generierung von Proxies für mehrere Klassen, die eine Schnittstelle implementieren, ohne für jede Klasse eine separate Klasse zu erstellen.

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    // Handler für dynamische Proxies
    class DynamicServiceInvocationHandler implements InvocationHandler {
        private final Object target; // Zielobjekt
    
        public DynamicServiceInvocationHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("Vor dem Methodenaufruf " + method.getName());
            Object result = method.invoke(target, args); // Aufruf der Zielmethode
            System.out.println("Nach dem Methodenaufruf " + method.getName());
            return result;
        }
    }
    
    // Beispielnutzung (für die Service-Schnittstelle des statischen Proxies)
    // Service realService = new RealService();
    // Service proxy = (Service) Proxy.newProxyInstance(
    //     realService.getClass().getClassLoader(),
    //     realService.getClass().getInterfaces(),
    //     new DynamicServiceInvocationHandler(realService));
    // proxy.doSomething();
    
  • CGLIB Proxy: Basierend auf Bytecode-Generation und erfordert keine Schnittstelle. Kann konkrete Klassen proxyen (sofern sie nicht final sind und ihre Methoden nicht final sind). Ist in bestimmten Szenarien leistungsfähiger als der Standard-Dynamic Proxy.

    // Beispiel für CGLIB (benötigt externe Bibliothek)
    // public class RealService {
    //     public void doSomething() {
    //         System.out.println("Echte Aktion");
    //     }
    // }
    
    // 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("Vor dem Methodenaufruf " + method.getName());
    //         Object result = proxy.invokeSuper(obj, args); // Aufruf der Superklasse (Originalobjekt)
    //         System.out.println("Nach dem Methodenaufruf " + method.getName());
    //         return result;
    //     }
    // }
    
    // // Beispielnutzung:
    // // Enhancer enhancer = new Enhancer();
    // // enhancer.setSuperclass(RealService.class);
    // // enhancer.setCallback(new CglibServiceInterceptor());
    // // RealService proxy = (RealService) enhancer.create();
    // // proxy.doSomething();
    

Hauptunterschiede:

Proxy-Typ Benötigt Schnittstelle Generierung Flexibilität Leistung Anwendung
Statisch Ja Manuell Niedrig (für jede Klasse) Hoch Einfache Fälle, bekannte Struktur
Dynamisch Ja Zur Laufzeit Hoch (für Schnittstellen) Mittel Gemeinsame Logik für Schnittstellen, AOP
CGLIB Nein Zur Laufzeit Hoch (für Klassen) Hoch AOP, Proxy von Klassen ohne Schnittstellen