Ի՞նչ տեսակի պրոքսի սերվերներ եք գիտե՞ք։
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, դասերի պրոքսիավորում առանց ինտերֆեյսի |