Какие виды прокси-серверов вы знаете?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech 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 | Нет | Во время выполнения | Высокая (для классов) | Высокая | АОП, проксирование классов без интерфейсов |