Sobes.tech
Middle

Ի՞նչ տեսակի պրոքսի սերվերներ եք գիտե՞ք։

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;
    
    // Հետաբերյալ handler-ը դինամիկ պրոքսի համար
    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();
    

Հիմնական տարբերությունները՝

Տեսակ պրոքսի Պահանջում է ինտերֆեյս Գեներացում Լայնություն Արդյունավետություն Կիրառում
Կայուն (Static) Այո Հատուկ Նվազ (յուրաքանչյուր դասի համար) Բարձր Պարզ դեպքեր, երբ կառուցվածքը հայտնի է
Դինամիկ (Dynamic) Այո Ժամանակի ընթացքում Բարձր (ինտերֆեյսների համար) Միջին Ընդհանուր տրամաբանություն ինտերֆեյսների համար, AOP
CGLIB Ոչ Ժամանակի ընթացքում Բարձր (դասերի համար) Բարձր AOP, դասերի պրոքսիավորում առանց ինտերֆեյսի