Jakie rodzaje serwerów proxy znasz?
sobes.tech AI
Odpowiedź od AI
W Javie istnieją następujące rodzaje proxy:
-
Proxy statyczne (Static Proxy): Implementuje się je poprzez utworzenie osobnej klasy opakowującej, która zawiera odwołanie do rzeczywistego obiektu i deleguje do niego wywołania metod, dodając własną logikę (np. logowanie, autoryzację).
// Interfejs interface Service { void doSomething(); } // Rzeczywisty obiekt class RealService implements Service { @Override public void doSomething() { System.out.println("Rzeczywiste działanie"); } } // Proxy statyczne class StaticServiceProxy implements Service { private final Service realService; public StaticServiceProxy(Service realService) { this.realService = realService; } @Override public void doSomething() { System.out.println("Przed wywołaniem rzeczywistej metody"); realService.doSomething(); System.out.println("Po wywołaniu rzeczywistej metody"); } } -
Proxy dynamiczne (Dynamic Proxy): Tworzone w czasie wykonywania z użyciem Reflection API i wymagają, aby obiekt proxy implementował co najmniej jeden interfejs. Pozwalają generować proxy dla wielu klas implementujących ten sam interfejs, bez konieczności tworzenia osobnej klasy dla każdej z nich.
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; // Obsługa wywołań dla proxy dynamicznego class DynamicServiceInvocationHandler implements InvocationHandler { private final Object target; // Obiekt docelowy public DynamicServiceInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Przed wywołaniem metody " + method.getName()); Object result = method.invoke(target, args); // Wywołanie metody obiektu docelowego System.out.println("Po wywołaniu metody " + method.getName()); return result; } } // Przykład użycia (dla interfejsu Service z przykładu statycznego proxy) // Service realService = new RealService(); // Service proxy = (Service) Proxy.newProxyInstance( // realService.getClass().getClassLoader(), // realService.getClass().getInterfaces(), // new DynamicServiceInvocationHandler(realService)); // proxy.doSomething(); -
Proxy CGLIB: Oparty na generowaniu kodu bajtowego i nie wymaga implementacji interfejsu. Może proxyować konkretne klasy (jeśli nie są finalne i metody nie są finalne). W niektórych scenariuszach jest wydajniejszy niż standardowy proxy dynamiczny.
// Przykład użycia CGLIB (wymaga zewnętrznej biblioteki) // public class RealService { // public void doSomething() { // System.out.println("Rzeczywiste działanie"); // } // } // 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("Przed wywołaniem metody " + method.getName()); // Object result = proxy.invokeSuper(obj, args); // Wywołanie metody nadklasy (oryginalnego obiektu) // System.out.println("Po wywołaniu metody " + method.getName()); // return result; // } // } // // Przykład użycia: // // Enhancer enhancer = new Enhancer(); // // enhancer.setSuperclass(RealService.class); // // enhancer.setCallback(new CglibServiceInterceptor()); // // RealService proxy = (RealService) enhancer.create(); // // proxy.doSomething();
Główne różnice:
| Typ Proxy | Wymaga interfejsu | Generacja | Elastyczność | Wydajność | Zastosowanie |
|---|---|---|---|---|---|
| Statyczny | Tak | Ręcznie | Niska (dla każdej klasy) | Wysoka | Proste przypadki, znana struktura |
| Dynamiczny | Tak | W czasie działania | Wysoka (dla interfejsów) | Średnia | Wspólna logika dla interfejsów, AOP |
| CGLIB | Nie | W czasie działania | Wysoka (dla klas) | Wysoka | AOP, proxy dla klas bez interfejsów |