Кадом намудҳои серверҳои proxy-ро медонед?
sobes.tech AI
Ҷавоб аз AI
У Java съществуват следните видове прокси:
-
Статичен (Static Proxy): Реализира се чрез създаване на отделен клас-обвивка, който съдържа препратка към реалния обект и делегира му извикванията на методи, като добавя собствена логика (например логване, авторизация).
// Интерфейс interface Service { void doSomething(); } // Реален обект class RealService implements Service { @Override public void doSomething() { System.out.println("Реално действие"); } } // Статичен прокси class StaticServiceProxy implements Service { private final Service realService; public StaticServiceProxy(Service realService) { this.realService = realService; } @Override public void doSomething() { System.out.println("Преди извикването на реалния метод"); realService.doSomething(); System.out.println("След извикването на реалния метод"); } } -
Динамичен (Dynamic Proxy): Създава се по време на изпълнение с използване на Reflection API и изисква проксираният обект да реализира поне един интерфейс. Позволява генериране на прокси за множество класове, реализиращи един интерфейс, без да се създава отделен клас за всеки.
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; // Обработчик на извиквания за динамичен прокси class DynamicServiceInvocationHandler implements InvocationHandler { private final Object target; // Целевият обект public DynamicServiceInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Преди извикването на метода " + method.getName()); Object result = method.invoke(target, args); // Извикване на метода на целевия обект System.out.println("След извикването на метода " + method.getName()); return result; } } // Пример за използване (за интерфейса Service от статичния пример) // Service realService = new RealService(); // Service proxy = (Service) Proxy.newProxyInstance( // realService.getClass().getClassLoader(), // realService.getClass().getInterfaces(), // new DynamicServiceInvocationHandler(realService)); // proxy.doSomething(); -
CGLIB Proxy: Основава се на генериране на байткод и не изисква реализиране на интерфейс. Може да проксира конкретни класове (ако не са финални и методите не са финални). По-ефективен е в някои сценарии в сравнение със стандартния динамичен прокси.
// Пример за използване на CGLIB (изисква външна библиотека) // public class RealService { // public void doSomething() { // System.out.println("Реално действие"); // } // } // 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("Преди извикването на метода " + method.getName()); // Object result = proxy.invokeSuper(obj, args); // Позоваването на метода на суперкласа (оригиналния обект) // System.out.println("След извикването на метода " + method.getName()); // return result; // } // } // // Пример за използване: // // Enhancer enhancer = new Enhancer(); // // enhancer.setSuperclass(RealService.class); // // enhancer.setCallback(new CglibServiceInterceptor()); // // RealService proxy = (RealService) enhancer.create(); // // proxy.doSomething();
Основни разлики:
| Вид прокси | Изисква интерфейс | Генериране | Гъвкавост | Производителност | Приложение |
|---|---|---|---|---|---|
| Статичен | Да | Вручную | Ниска (за всеки клас) | Висока | Простите случаи, когато структурата е известна |
| Динамически | Да | Во време на изпълнение | Висока (за интерфейси) | Средна | Общи логики за интерфейси, АОП |
| CGLIB | Не | Во време на изпълнение | Висока (за класове) | Висока | АОП, проксиране на класове без интерфейси |