Sobes.tech
Middle

Кадом намудҳои серверҳои 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 Не Во време на изпълнение Висока (за класове) Висока АОП, проксиране на класове без интерфейси