2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
प्रॉक्सी इति एकं मोडं निर्दिशति यस्मिन् A वस्तुनः अन्यं वस्तु B धारयित्वा B इत्यस्य समानं व्यवहारं कर्तुं शक्नोति । प्रोटोकॉलं बहिः जगति उद्घाटयितुं B प्रायः एकं अन्तरफलकं कार्यान्वितं करोति, A अपि अन्तरफलकं कार्यान्वयिष्यति । परन्तु B "वास्तविक" कार्यान्वयनवर्गः अस्ति, यदा A अधिकं "वर्चुअल्" अस्ति । यद्यपि क "छद्मसेना" अस्ति तथापि खस्य विधिं आह्वयितुं पूर्वं पश्चात् च B वर्धयितुं अन्यकार्यं कर्तुं शक्नोति । Spring AOP कोडस्य गतिशीलं "बुननम्" पूर्णं कर्तुं गतिशीलप्रॉक्सी इत्यस्य उपयोगं करोति ।
प्रॉक्सी इत्यस्य उपयोगस्य लाभः अस्मात् परं गच्छति यदि परियोजना अन्येन परियोजनायाः अन्तरफलके अवलम्बते, परन्तु अन्यस्य परियोजनायाः अन्तरफलकं अस्थिरं भवति तथा च प्रोटोकॉलः प्रायः परिवर्तितः भवति तदा भवन्तः प्रॉक्सी इत्यस्य उपयोगं कर्तुं शक्नुवन्ति केवलं प्रॉक्सी परिवर्तयितुं आवश्यकं, न तु एकैकं व्यापारसङ्केतं परिवर्तयतु। अस्मिन् अर्थे वयं सर्वेषां अन्तरफलकानां कृते एतत् कर्तुं शक्नुमः ये बाह्यजगति समायोजयन्ति येन बहिः कोडः अस्माकं कोड् आक्रमणं न करोति इति एतत् रक्षात्मकं प्रोग्रामिंग् इति कथ्यते । प्रॉक्सी-करणाय अन्ये बहवः अनुप्रयोगाः भवितुम् अर्हन्ति ।
उपर्युक्ते उदाहरणे A वर्गः B धारयितुं हार्ड-कोड् कृतः अस्ति, यत् B इत्यस्य स्थिरप्रॉक्सी अस्ति । यदि A प्रॉक्सी इत्यस्य वस्तु अनिश्चितं भवति तर्हि सः गतिशीलः प्रॉक्सी अस्ति । सम्प्रति गतिशीलप्रॉक्सी, jdk गतिशीलप्रॉक्सी तथा cglib गतिशीलप्रॉक्सी इत्यस्य सामान्यकार्यन्वयनद्वयम् अस्ति ।
स्थिर-प्रॉक्सी एकः डिजाइन-प्रतिरूपः, प्रॉक्सी-प्रतिरूपस्य च एकः प्रकारः अस्ति । स्थिरप्रॉक्सीमध्ये प्रोग्रामस्य चालनात् पूर्वं प्रॉक्सीवर्गः परिभाषितः भवति, तथा च प्रॉक्सीवर्गस्य प्रॉक्सीवर्गस्य च सम्बन्धः संकलनसमये निर्धारितः भवति अस्य अर्थः अस्ति यत् प्रॉक्सी क्लास् तथा प्रॉक्सी क्लास् इत्येतयोः द्वयोः अपि एकमेव अन्तरफलकं कार्यान्वितं भवति अथवा एकमेव मातापितृवर्गः आन्तरिकरूपेण प्रॉक्सी क्लास् इत्यस्य एकं उदाहरणं धारयति तथा च एकस्मिन् समये प्रॉक्सी क्लास् इत्यस्य मेथड्स् आह्वयति , इदं आह्वानात् पूर्वं पश्चात् च स्वस्य केचन कार्याणि योजयितुं शक्नोति, यथा लॉगिंग्, अनुमतिपरीक्षणं, लेनदेनप्रक्रियाकरणम् इत्यादयः ।
स्थिरप्रॉक्सी इत्यस्य त्रयः घटकाः सन्ति : अमूर्त-अन्तरफलकं, प्रॉक्सी-वर्गः, प्रॉक्सी-वर्गः च अस्य कार्यान्वयनस्य उदाहरणानि निम्नलिखितरूपेण सन्ति ।
- public interface TargetInteface {
- void method1();
- void method2();
- int method3(Integer i);
- }
- public class TargetProxy implements TargetInteface {
-
- private Target target =new Target();
- @Override
- public void method1() {
- System.out.println("执行方法前...");
- target.method1();
- System.out.println("执行方法后...");
- }
-
- @Override
- public void method2() {
- System.out.println("执行方法前...");
- target.method2();
- System.out.println("执行方法后...");
- }
-
- @Override
- public int method3(Integer i) {
- System.out.println("执行方法前...");
- int method3 = target.method3(i);
- System.out.println("执行方法后...");
- return method3;
- }
- }
- public class Target implements TargetInteface {
- @Override
- public void method1() {
- System.out.println(" Target method1 running ...");
- }
-
- @Override
- public void method2() {
- System.out.println("Target method2 running ...");
- }
-
- @Override
- public int method3(Integer i) {
- System.out.println("Target method3 running ...");
- return i;
- }
- }
- public class TargetUser {
-
- public static void main(String[] args) {
- TargetInteface target = new TargetProxy();
- target.method1();
- System.out.println("-----------------------------");
- target.method2();
- System.out.println("-----------------------------");
- System.out.println(target.method3(3));
- }
- }
परिणामनिर्गमः : १.
विधिं निष्पादनात् पूर्वं...
लक्ष्यविधिः1 चलति ...
विधिं निष्पादयित्वा...
-----------------------------
विधिं निष्पादनात् पूर्वं...
लक्ष्यविधिः2 चलति ...
विधिं निष्पादयित्वा...
-----------------------------
विधिं निष्पादनात् पूर्वं...
लक्ष्यविधिः3 चलति ...
विधिं निष्पादयित्वा...
3
स्थिरकारकाणां कार्यान्वयनात् एतत् द्रष्टुं न कठिनं यत् स्थिरकारकाणां लाभाः सरलाः कार्यान्वयनम्, सुलभतया च अवगन्तुं शक्यन्ते । परन्तु तस्य दोषाः अपि स्पष्टाः सन्ति, अर्थात् यदा कदापि भवन्तः नूतनवर्गे प्रॉक्सीकार्यक्षमतां योजयितुं प्रवृत्ताः भवन्ति तदा भवन्तः हस्तचलितरूपेण नूतनं प्रॉक्सीवर्गं निर्मातुम् अर्हन्ति, येन वर्गानां संख्यायां तीव्रवृद्धिः, अनुरक्षणव्ययस्य च वृद्धिः भविष्यति . तस्मिन् एव काले प्रॉक्सी-वर्गस्य प्रॉक्सी-वर्गस्य च युग्मनस्य प्रमाणम् अत्यधिकं भवति यदा प्रॉक्सी-वर्गे विधिः योजितः, विलोप्यते, परिवर्तितः वा भवति तदा तत्सम्बद्धाः पद्धतयः अपि प्रॉक्सी-वर्गे योजिताः, विलोपिताः, परिवर्तिताः वा भवेयुः , यत् कोड-अनुरक्षणं सुधरयति । अन्यत् समस्या अस्ति यत् यदा प्रॉक्सी-वस्तु बहुलक्ष्य-अन्तरफलकानां कार्यान्वयन-वर्गान् प्रॉक्सी करोति तदा बहु-कार्यन्वयन-वर्गेषु भिन्नाः पद्धतयः भवितुमर्हन्ति यतः प्रॉक्सी-वस्तु लक्ष्य-वस्तुनः समानं अन्तरफलकं कार्यान्वितुं अर्हति (वास्तवतः समावेश-सम्बन्धः) be written असंख्यानि पद्धतयः सहजतया प्रफुल्लितं कठिनं च कोडं जनयितुं शक्नुवन्ति ।
गतिशीलप्रॉक्सी इत्यस्य मूलविचारः अस्ति यत् मूलवस्तुसङ्केतं परिवर्तनं विना प्रॉक्सीवस्तुद्वारा मूलवस्तुं परोक्षरूपेण अभिगन्तुं, अभिगमनात् पूर्वं पश्चात् च अतिरिक्तक्रियाः कर्तुं च
गतिशीलप्रॉक्सी इत्यस्य कार्यान्वयनसिद्धान्तः मुख्यतया जावा इत्यस्य प्रतिबिम्बतन्त्रे आधारितः अस्ति । गतिशीलप्रॉक्सी-उपयोगे भवद्भिः एकं अन्तरफलकं वा अन्तरफलकसमूहं वा परिभाषितव्यं यत् प्रॉक्सी-वर्गस्य (प्रॉक्सी-वस्तु) व्यवहारं परिभाषयति ।ततः, भवद्भिः एकं कार्यान्वयनम् लिखितव्यम्InvocationHandler
Interface class, अस्मिन् क्लास् मध्ये logic अस्ति यत् proxy object इत्यत्र method calls इत्यस्मात् पूर्वं पश्चात् च निष्पादितं भवति ।आह्वानं कुर्वन्Proxy.newProxyInstance()
method, interface इत्यस्य class loader इत्यस्मिन् pass, interface array andInvocationHandler
ऑब्जेक्ट्, जावा गतिशीलरूपेण एकं प्रॉक्सी क्लास् जनयिष्यति यत् रनटाइम् इत्यत्र निर्दिष्टं अन्तरफलकं कार्यान्वितं करोति, तथा च मेथड् आह्वानं प्रत्याययतिInvocationHandler
प्रक्रियां कर्तुं विषयाः।यदा प्रॉक्सी-वस्तुनः मेथड् आह्वयते तदा तत् वस्तुतः आह्वयतिInvocationHandler
अन्तरफलकम्invoke()
विधिः, यस्मिन् भवान् विधिनाम, पैरामीटर् इत्यादीनां सूचनानां आधारेण किञ्चित् पूर्वसंसाधनतर्कं कर्तुं शक्नोति, ततः प्रतिबिम्बद्वारा प्रॉक्सीवस्तुनः तत्सम्बद्धं विधिं आह्वयितुं शक्नोति
तदनन्तरं वयं द्वौ गतिशीलप्रॉक्सी परिचययामः : JDK Proxy तथा CGLib
JDK Proxy गतिशीलरूपेण प्रॉक्सी वर्गान् जनयितुं जावा इत्यस्य प्रतिबिम्बतन्त्रस्य उपयोगं करोति । विशेषतः, २.Proxy
वर्गः उपयोगं करिष्यतिProxyGenerator
class (यद्यपि एषः वर्गः सार्वजनिकः एपिआइ नास्ति तथापि JDK इत्यस्य अन्तः गतिशीलप्रॉक्सीकरणं कार्यान्वितुं कुञ्जी अस्ति) प्रॉक्सीवर्गस्य बाइटकोड् जनयितुं JVM मध्ये लोड् कर्तुं चउत्पन्नः प्रॉक्सी वर्गः इत्यस्मात् उत्तराधिकारं प्राप्स्यतिjava.lang.reflect.Proxy
class कृत्वा निर्दिष्टं अन्तरफलकं कार्यान्वितम्।प्रॉक्सी क्लास् इत्यस्य मेथड् इत्यत्र तत् आह्वयिष्यतेInvocationHandler
इत्यस्यinvoke
विधिः, प्रक्रियायाः कृते मेथड् आह्वानं प्रोसेसरं प्रति अग्रे प्रेषयन्तु ।
तदतिरिक्तं, कार्यक्षमतां सुधारयितुम्, JDK Proxy उत्पन्नस्य प्रॉक्सी वर्गस्य Class ऑब्जेक्ट् कैशिंग् कर्तुं कैशिंग् तन्त्रमपि प्रदाति । एवं प्रकारेण यदा भवन्तः समानप्रकारस्य प्रॉक्सी ऑब्जेक्ट् निर्मातुम् अर्हन्ति तदा भवन्तः प्रत्यक्षतया प्रॉक्सी क्लास् इत्यस्य Class ऑब्जेक्ट् पुनः उत्पन्नं विना cache तः प्राप्तुं शक्नुवन्ति ।कैशिंग् मार्गेण क्रियतेWeakCache
वर्गेन कार्यान्वितं, एतत् संग्रहणवस्तूनाम् दुर्बलसन्दर्भान् उपयुङ्क्ते येन JVM कचरासङ्ग्रहं कुर्वन् यत् संग्रहणवस्तूनि पुनः प्रयुक्तानि न सन्ति, ते स्वयमेव स्वच्छाः भवितुम् अर्हन्ति
- public interface TargetInteface {
- void method1();
- void method2();
- int method3(Integer i);
- }
- public class Target implements TargetInteface {
- @Override
- public void method1() {
- System.out.println("method1 running ...");
- }
-
- @Override
- public void method2() {
- System.out.println("method2 running ...");
- }
-
- @Override
- public int method3(Integer i) {
- System.out.println("method3 running ...");
- return i;
- }
- }
InvocationHandler
अन्तरफलकं पुनर्लेखनं च कुर्वन्तुinvoke
प्रक्रिया।अस्तिinvoke
मेथड् मध्ये, भवान् कस्टम् लॉजिक्, यथा लॉगिंग्, परमिशन चेकिंग् इत्यादीन् योजयितुं शक्नोति, तथा च रिफ्लेक्शन् मार्गेण मूल क्लास मेथड् आह्वयितुं शक्नोति ।Proxy.newProxyInstance
मेथड्, क्लास लोडर्, इन्टरफेस् एरे च पासिंग्InvocationHandler
प्रॉक्सी ऑब्जेक्ट्स् गतिशीलरूपेण जनयितुं उदाहरणम् । एषा विधिः निर्दिष्टं अन्तरफलकं कार्यान्वितं प्रॉक्सी वर्गदृष्टान्तं प्रत्यागच्छति ।- public class TargetProxy {
- public static <T> Object getTarget(T t) {
- //新构建了一个 新的 代理类的对象
- return Proxy.newProxyInstance(t.getClass().getClassLoader(), t.getClass().getInterfaces(), new InvocationHandler() {
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- // proxy就是目标对象t,method就是调用目标对象中方法,args就是调用目标对象中方法的参数。
- //比如说:代理对象.method1(),这时proxy就是目标类,method1就是method,args就是method1方法参数。
- System.out.println("执行方法前...");
- Object invoke = method.invoke(t, args);
- System.out.println("执行方法后...");
- return invoke;
- }
- });
- }
- }
InvocationHandler
इत्यस्यinvoke
विधिः, यस्मिन् कस्टम् तर्कः निष्पादितः भवति ततः मूलवर्गस्य मेथड् उच्यते ।- public class TargetUser {
-
- public static void main(String[] args) {
- TargetInteface target = (TargetInteface) TargetProxy.getTarget(new Target());
- target.method1();
- System.out.println("-----------------------------");
- target.method2();
- System.out.println("-----------------------------");
- System.out.println(target.method3(3));
- }
- }
परिणामनिर्गमः : १.
विधिं निष्पादनात् पूर्वं...
विधि1 चालयन् ...
विधिं निष्पादयित्वा...
-----------------------------
विधिं निष्पादनात् पूर्वं...
विधि२ चालयन् ...
विधिं निष्पादयित्वा...
-----------------------------
विधिं निष्पादनात् पूर्वं...
विधि३ चालयन् ...
विधिं निष्पादयित्वा...
3
MethodInterceptor
interface इत्येतत् मेथड् इन्टरसेप्टर् परिभाषितुं, यत् प्रॉक्सी ऑब्जेक्ट् इत्यस्य मेथड् कॉल् इत्यस्मात् पूर्वं पश्चात् च कस्टम् लॉजिक् निष्पादयिष्यति, यथा प्रीप्रोसेसिंग्, पोस्टप्रोसेसिंग्, अपवादनियन्त्रणम् इत्यादयः- import net.sf.cglib.proxy.Enhancer;
- import net.sf.cglib.proxy.MethodInterceptor;
- import net.sf.cglib.proxy.MethodProxy;
- import java.lang.reflect.Method;
- public class Target {
- public void method1() {
- System.out.println("method1 running ...");
- }
-
- public void method2() {
- System.out.println("method2 running ...");
- }
-
- public int method3(Integer i) {
- System.out.println("method3 running ...");
- return i;
- }
- }
MethodInterceptor
interface class तथा override इतिintercept
प्रक्रिया। अस्मिन् पद्धत्या प्रॉक्सी तर्कं लिखन्तु ।Enhancer
class प्रॉक्सी ऑब्जेक्ट्स् निर्मातुं ।भवद्भिः प्रॉक्सीड् क्लास् (viasetSuperclass
विधिः) तथा कॉलबैक् (viasetCallback
विधिः MethodInterceptor कार्यान्वयनवर्गं सेट् करोति) ।- public class TargetProxy {
- public static <T> Object getProxy(T t) {
- Enhancer en = new Enhancer(); //帮我们生成代理对象
- en.setSuperclass(t.getClass());//设置要代理的目标类
- en.setCallback(new MethodInterceptor() {//代理要做什么
- @Override
- public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
- System.out.println("执行方法前。。。");
- //调用原有方法
- Object invoke = methodProxy.invokeSuper(object, args);
- // Object invoke = method.invoke(t, args);// 作用等同与上面。
- System.out.println("执行方法后。。。");
- return invoke;
- }
- });
- return en.create();
- }
- }
intercept
विधिषु प्रॉक्सी तर्कः ।- public class TargetUser {
-
- public static void main(String[] args) {
- Target target = (Target) TargetProxy.getProxy(new Target());
- System.out.println(target.getClass().getName());
- target.method1();
- }
-
- }
परिणामनिर्गमः : १.
com.heaboy.aopdemo.cglibproxy.लक्ष्यम्ईनजएकःनगङरखय्गजीलअहम्खf9f41fb8
विधिं निष्पादयितुं पूर्वं । . .
विधि1 चालयन् ...
विधिं निष्पादयित्वा । . .
लाभ:
अभावः : १.
प्रॉक्सी वस्तुप्रकारः : १.JDK Proxy केवलं तान् वर्गान् प्रॉक्सी कर्तुं शक्नोति ये अन्तरफलकान् कार्यान्वन्ति यदा CGLib प्रत्यक्षतया साधारणवर्गान् प्रॉक्सी कर्तुं शक्नोति;
प्रदर्शनम्: CGLib रनटाइम् इत्यत्र प्रॉक्सी क्लास् इत्यस्य उपवर्गान् जनयति तथा च सामान्यतया JDK Proxy इत्यस्मात् किञ्चित् उत्तमं प्रदर्शनं करोति इति मन्यते । परन्तु अधिकांशेषु परिदृश्येषु एषः कार्यप्रदर्शनभेदः महत्त्वपूर्णः नास्ति ।
प्रयोक्तव्याः दृश्याः : १. यदि लक्ष्यवस्तु पूर्वमेव अन्तरफलकं कार्यान्वितं करोति तर्हि JDK Proxy इत्यस्य उपयोगः सरलः सरलः च विकल्पः अस्ति । यदि भवान् एकं वर्गं प्रॉक्सी कर्तुं इच्छति यत् अन्तरफलकं कार्यान्वितं न करोति तर्हि भवता CGLib इत्यस्य उपयोगः अवश्यं करणीयः ।
विश्वसिति:JDK Proxy इत्यस्य कृते अतिरिक्तनिर्भरतायाः आवश्यकता नास्ति यतोहि एतत् Java कोर पुस्तकालयस्य भागः अस्ति यदा CGLib इत्यस्य कृते CGLib पुस्तकालयं परियोजनानिर्भरतायाः रूपेण योजयितुं आवश्यकम् अस्ति;
JDK Proxy इति एकं कार्यं यत् जावाभाषायाः सह आगच्छति तथा च तृतीयपक्षवर्गान् लोड् कृत्वा कार्यान्वितुं आवश्यकता नास्ति;
जावा JDK Proxy कृते स्थिरसमर्थनं प्रदाति, तथा च JDK Proxy इत्यस्य उन्नयनं अद्यतनीकरणं च निरन्तरं करिष्यति उदाहरणार्थं, Java 8 संस्करणे JDK Proxy इत्यस्य कार्यक्षमता पूर्वसंस्करणानाम् अपेक्षया बहु उन्नता अस्ति
JDK Proxy interceptors तथा reflection इत्येतयोः माध्यमेन कार्यान्वितं भवति;
JDK प्रॉक्सी केवलं तान् प्रॉक्सी वर्गान् कर्तुं शक्नोति ये अन्तरफलकानि उत्तराधिकारं गृह्णन्ति;
JDK Proxy इत्यस्य कार्यान्वयनम् आह्वानं च तुल्यकालिकरूपेण सरलम् अस्ति;
CGLib तृतीयपक्षेण प्रदत्तं साधनं, ASM आधारेण कार्यान्वितं, तुल्यकालिकरूपेण उच्चप्रदर्शनं च अस्ति;
CGLib इत्यस्य अन्तरफलकस्य माध्यमेन कार्यान्वयनस्य आवश्यकता नास्ति, उपवर्गस्य कार्यान्वयनेन आह्वयते ।
स्थिर प्रॉक्सी : १. संकलनस्य समये स्थिराः प्रॉक्सीः निर्धारिताः भवन्ति ।
स्थिरप्रॉक्सी इत्यस्य प्रॉक्सी वर्गः संकलनसमये विद्यते, अतः सः केवलं कार्यक्रमस्य चालने विशिष्टवर्गान् प्रॉक्सी कर्तुं शक्नोति, तथा च गतिशीलरूपेण निर्णयं कर्तुं न शक्नोति यत् के वर्गाः प्रॉक्सी कर्तव्याः इति
स्थिरप्रॉक्सी मूलवस्तुनः मेथड् कॉल् लपेटयति तथा च आह्वानात् पूर्वं पश्चात् च अतिरिक्तं तर्कं योजयितुं शक्नोति, परन्तु प्रॉक्सी वर्गं पूर्वमेव लिखितव्यं भवति, येन कोडस्य परिमाणं वर्धते
स्थिरप्रॉक्सी स्पष्टतया कोडमध्ये प्रॉक्सीवस्तुं निर्दिशति तथा च उपयोगाय तुल्यकालिकरूपेण सहजं भवति, परन्तु नूतनानि प्रॉक्सीवर्गाणि योजयितुं पुनः संकलनस्य आवश्यकता भवति ।
गतिशील प्रॉक्सी : १. डायनामिक प्रॉक्सी पूर्वमेव प्रॉक्सी क्लास् न लिखित्वा रनटाइम् इत्यत्र प्रॉक्सी ऑब्जेक्ट्स् निर्माति । प्रॉक्सी क्लास् तथा प्रॉक्सी ऑब्जेक्ट्स् गतिशीलरूपेण जनयितुं जावा इत्यस्य परावर्तनतन्त्रस्य उपयोगं कुर्वन्तु ।
गतिशीलप्रॉक्सी अन्तरफलकेषु आधारिताः सन्ति तथा च java.lang.reflect.Proxy वर्गस्य तथा java.lang.reflect.InvocationHandler अन्तरफलकस्य माध्यमेन कार्यान्विताः भवन्ति ।
गतिशीलप्रॉक्सी बहुविधानाम् अन्तरफलकानां वर्गान् प्रॉक्सी कर्तुं शक्नोति तथा च गतिशीलरूपेण निर्णयं कर्तुं शक्नोति यत् के वर्गाः प्रॉक्सी कर्तव्याः इति । रनटाइम् इत्यत्र आवश्यकतानुसारं भिन्न-भिन्न-वस्तूनाम् कृते प्रॉक्सी-जननं कर्तुं शक्यते, येन अधिकं लचीलता प्राप्यते ।
गतिशीलप्रॉक्सी प्रत्येकस्य प्रॉक्सीवर्गस्य कृते विशिष्टं प्रॉक्सीवर्गं लिखितुं आवश्यकता नास्ति, यत् अधिकं लचीलं भवति तथा च कोडं रक्षति ।
डायनामिक एजेण्ट् प्रॉक्सी ऑब्जेक्ट् इत्यत्र मेथड् कॉल् इत्यस्मात् पूर्वं पश्चात् च कस्टम् लॉजिक् योजयितुं शक्नुवन्ति, यथा लॉगिंग्, लेनदेन प्रबन्धनम् इत्यादयः । गतिशीलप्रॉक्सी इत्यस्य दोषः अस्ति यत् स्थिरप्रॉक्सी इत्यस्य तुलने रनटाइम् इत्यत्र प्रॉक्सी ऑब्जेक्ट् जनयितुं निश्चितं कार्यप्रदर्शनस्य उपरिभारस्य आवश्यकता भवति ।
स्थिरप्रॉक्सी निम्नलिखितपरिदृश्यानां कृते उपयुक्ताः सन्ति ।
यदा लक्ष्यवस्तूनाम् (प्रॉक्सीवस्तूनाम्) संख्या सीमितं निर्धारितं च भवति तदा प्रॉक्सीवर्गान् मैन्युअल् रूपेण लिखित्वा स्थिरप्रॉक्सी कार्यान्वितुं शक्यते । स्थिरप्रॉक्सी संकलनसमये प्रॉक्सीवर्गान् निर्मान्ति, अतः तेषां रनटाइम् इत्यत्र उत्तमं प्रदर्शनं भवति ।
स्थिरप्रॉक्सी लक्ष्यवस्तुं समाहितं कुर्वन्ति तथा च मूलसङ्केतं परिवर्तनं विना अतिरिक्तकार्यं योजयन्ति । एतेन स्थिरप्रॉक्सी प्रायः लॉगिंग्, लेनदेनप्रबन्धनम् इत्यादीनां क्रॉस्-कटिंग् चिन्तानां कृते उपयुज्यन्ते ।
गतिशीलप्रॉक्सी निम्नलिखितपरिदृश्यानां कृते उपयुक्तः अस्ति:
यदा लक्ष्यवस्तूनाम् संख्या अनिश्चिता भवति अथवा पूर्वमेव निर्धारयितुं न शक्यते तदा गतिशीलाः प्रॉक्सी अधिकसुलभतया प्रॉक्सीवस्तूनाम् उत्पन्नं कर्तुं शक्नुवन्ति । एतत् रनटाइम् इत्यत्र प्रॉक्सी क्लास् तथा प्रॉक्सी ऑब्जेक्ट्स् जनयति, बहुविधप्रॉक्सी क्लास् मैन्युअल् रूपेण लेखनस्य क्लिष्टं कार्यं परिहरति ।
गतिशीलप्रॉक्सी रनटाइम् इत्यत्र लक्ष्यवस्तूनाम् प्रॉक्सीव्यवहारं योजयितुं, निष्कासयितुं, परिवर्तयितुं वा लचीलतां प्रदाति । एतेन गतिशीलप्रॉक्सी प्रायः एओपी (पक्ष-उन्मुखप्रोग्रामिंग) तथा आरपीसी (दूरस्थप्रक्रियाकॉल) इत्यादिषु अनुप्रयोगपरिदृश्येषु उपयुज्यते ।
ज्ञातव्यं यत् यतः गतिशीलाः प्रॉक्सीः रनटाइम् इत्यत्र प्रतिबिम्बतन्त्रस्य माध्यमेन प्रॉक्सीवर्गान् प्रॉक्सीवस्तुं च निर्मान्ति, तेषां कार्यक्षमता स्थिरप्रॉक्सीभ्यः किञ्चित् न्यूनं भवितुम् अर्हति तदतिरिक्तं गतिशीलप्रॉक्सी केवलं तान् प्रॉक्सी लक्ष्यं कर्तुं शक्नुवन्ति ये अन्तरफलकं कार्यान्वन्ति, यदा तु स्थिरप्रॉक्सीषु एतत् प्रतिबन्धं नास्ति ।
सारांशतः, स्थिरप्रॉक्सी तादृशानां परिदृश्यानां कृते उपयुक्ताः सन्ति यत्र लक्ष्यवस्तूनाम् संख्या सीमितं निश्चितं च भवति, तथा च एन्कैप्सुलेशनस्य अतिरिक्तकार्यस्य च आवश्यकता भवति, यदा तु गतिशीलप्रॉक्सी तेषु परिदृश्येषु उपयुक्ताः सन्ति यत्र लक्ष्यवस्तूनाम् संख्या अनिश्चिता भवति अथवा पूर्वमेव निर्धारयितुं न शक्यते, तथा च प्रॉक्सी व्यवहारं लचीलतया योजयितुं, विलोपयितुं, परिवर्तयितुं वा आवश्यकम् अस्ति । विशिष्टानि आवश्यकतानि परिस्थितिश्च आधारीकृत्य समुचितं एजेन्सीपद्धतिं चिनुत।
Spring AOP Spring framework इत्यस्मिन् महत्त्वपूर्णं मॉड्यूलम् अस्ति, यस्य उपयोगः पक्ष-उन्मुख-प्रोग्रामिंगस्य कार्यान्वयनार्थं भवति ।
साक्षात् सम्मुखं प्रोग्रामिंग् , इदं प्रोग्रामिंग् मॉडल् अस्ति यत् प्रोग्रामर्-जनाः कस्टम्-क्रॉसकटिङ्ग्-बिन्दून्-माध्यमेन मॉड्यूलरीकरणस्य अनुमतिं ददाति तथा च अनेकवर्गान् पुनःप्रयोज्य-मॉड्यूल्-मध्ये प्रभावितं कुर्वन्तः व्यवहारान् समाहितं कर्तुं शक्नोति उदाहरणम् : उदाहरणार्थं, log output, यदि भवान् AOP इत्यस्य उपयोगं न करोति तर्हि भवान् log output statements इत्येतत् सर्वेषु classes तथा methods मध्ये स्थापयितुं आवश्यकं तथापि AOP इत्यनेन log output statements इत्येतत् encapsulate कृत्वा a declarative manner इति क्लास् मध्ये प्रत्येकं क्लास् इत्यस्य उपयोगे log output स्वयमेव सम्पन्नं भवति ।
पक्ष-उन्मुख-प्रोग्रामिङ्गस्य विचारे कार्याणि द्वौ प्रकारौ विभक्ताः सन्ति
कोर बिजनेस: प्रवेशः, पञ्जीकरणं, परिवर्तनं, विलोपनं, परिवर्तनं, प्रश्नः च सर्वे कोरव्यापारः इति उच्यन्ते
परिधीय कार्य: लॉग्स् तथा लेनदेनप्रबन्धनं गौणपरिधीयसेवाः सन्ति।
आस्पेक्ट्-ओरिएंटेड् प्रोग्रामिंग् इत्यस्मिन् कोर-व्यापार-कार्यं परिधीय-कार्यं च स्वतन्त्रतया विकसितं भवति, ततः द्वयोः अपि युग्मितं न भवति, ततः एस्पेक्ट्-फंक्शन्-इत्येतत् कोर-व्यापार-कार्यं च एकत्र "बुनितम्" भवति, यत् एओपी इति कथ्यते
एओपी तान् परिवर्तयितुं शक्नोति ये व्यापारेण सह सम्बद्धाः न सन्ति,परन्तु सामान्यतया व्यावसायिकमॉड्यूलैः आह्वयितस्य तर्कस्य अथवा उत्तरदायित्वस्य (यथा लेनदेनप्रक्रियाकरणं, लॉगप्रबन्धनम्, अनुमतिनियन्त्रणम् इत्यादयः) कृते एतत् समाहितं भवति,सुलभम्प्रणाल्यां द्वितीयकसङ्केतं न्यूनीकरोतु,मॉड्यूलानां मध्ये युग्मनं न्यूनीकरोतु,तथाभविष्यस्य मापनीयतायाः परिपालनस्य च अनुकूलम्。
एओपी इत्यस्मिन् निम्नलिखितसंकल्पनाः सन्ति- १.
पक्षJ: Aspect केवलं अवधारणा अस्ति तस्य अनुरूपं कोऽपि विशिष्टः अन्तरफलकः वा वर्गः वा अस्ति ।
जॉइन बिन्दु : Connection point इति कार्यक्रमस्य निष्पादनस्य समये एकं बिन्दुं निर्दिशति, यथा विधि-आह्वानं, अपवाद-नियन्त्रणम् इत्यादयः । Spring AOP इत्यस्मिन् केवलं मेथड्-स्तरीय-जोइन्-बिन्दवः समर्थिताः सन्ति ।
उपदेशः : सूचना अर्थात् वयं परिभाषितपक्षे क्रॉस्-कटिंग् तर्कस्य त्रयः प्रकाराः सन्ति : "परितः", "पूर्वम्" "पश्चात्" च । अनेक AOP कार्यान्वयनरूपरेखासु, Advice प्रायः एकस्य अवरोधकस्य रूपेण कार्यं करोति, तथा च Join point इत्यस्य परितः संसाधितव्यं लिङ्करूपेण अनेकाः अवरोधकाः अपि समाविष्टाः भवितुम् अर्हन्ति
बिन्दुकट: Pointcut, यस्य उपयोगः join points इत्यस्य मेलनं कर्तुं भवति यत् AspectJ इत्यस्मिन् निहितं Join बिन्दुः Pointcut द्वारा फ़िल्टर करणीयम् ।
आमुख : परिचयः, एकं पक्षं घोषयितुं अनुमतिं ददाति यत् सल्लाहितवस्तूनि किमपि अतिरिक्तं अन्तरफलकं कार्यान्वयन्ति यत् ते वास्तवतः कार्यान्वितुं न कुर्वन्ति। यथा, लक्ष्यवर्गद्वयं प्रॉक्सी कर्तुं प्रॉक्सी ऑब्जेक्ट् इत्यस्य उपयोगः कर्तुं शक्यते ।
बुननम् : बुननम्, इदानीं यदा अस्माकं कृते संयोजनबिन्दवः, कटबिन्दवः, सूचनाः, पक्षाः च सन्ति, तानि कार्यक्रमे कथं प्रयोक्तव्यानि? तत्सत्यम्, इदं बुननम् अस्ति ।
एओपी प्रॉक्सी : AOP प्रॉक्सी तत् वस्तुं निर्दिशति यत् AOP कार्यान्वयनरूपरेखायां आस्पेक्ट् प्रोटोकॉलं कार्यान्वितं करोति । Spring AOP इत्यस्मिन् द्वौ प्रकारौ प्रॉक्सी स्तः, यथा JDK dynamic proxy तथा CGLIB dynamic proxy इति ।
लक्ष्यवस्तु: लक्ष्यवस्तु प्रॉक्सी क्रियमाणः वस्तु अस्ति।
Spring AOP JDK डायनामिक प्रॉक्सी तथा Cglib प्रचारस्य आधारेण कार्यान्वितं भवति, उभयत्र प्रॉक्सी पद्धतयः रनटाइम् पद्धतयः सन्ति, अतः तेषु संकलन-समय-प्रक्रियाकरणं नास्ति, अतः स्प्रिंग् जावा-सङ्केतस्य माध्यमेन कार्यान्वितम् अस्ति ।
बहुवर्गेषु अथवा वस्तुषु विकीर्णाः केचन सामान्यव्यवहाराः (यथा लॉगिंग्, लेनदेनप्रबन्धनम्, अनुमतिनियन्त्रणं, अन्तरफलकधारासीमीकरणं, अन्तरफलकशक्तिः इत्यादयः), एते व्यवहाराः प्रायः उच्यन्ते क्रॉस-कटिंग चिन्ता . यदि वयं प्रत्येकस्मिन् वर्गे वा वस्तुनि वा एतान् व्यवहारान् पुनः पुनः कार्यान्वयामः तर्हि तस्य कारणेन अनावश्यकं, जटिलं, कठिनं च कोडं भवति ।
एओपी क्रॉस-कटिंग्-चिन्तानां (यथा लॉगिंग्, लेनदेन-प्रबन्धनम्, अनुमति-नियन्त्रणं, अन्तरफलक-वर्तमान-सीमितीकरणं, अन्तरफलक-शक्तिः इत्यादयः) परिवर्तनं कर्तुं शक्नोति मूलव्यापार तर्क (कोर चिन्ता, मूल चिन्ता) २. चिन्तानां पृथक्त्वं प्राप्तुं केन्द्रीकरणात् पृथक् भवन्तु।
लॉगिंग् : लॉगिंग् एनोटेशन्स् अनुकूलितं कुर्वन्तु तथा च कोडस्य एकया पङ्क्तौ लॉगिंग् प्राप्तुं AOP इत्यस्य उपयोगं कुर्वन्तु ।
कार्यप्रदर्शनस्य आँकडा: अनुकूलनस्य विश्लेषणस्य च सुविधायै लक्ष्यपद्धतेः निष्पादनात् पूर्वं पश्चात् च पद्धतेः निष्पादनसमयस्य गणनाय AOP इत्यस्य उपयोगं कुर्वन्तु।
लेनदेनप्रबन्धनम् : १.@Transactional
एनोटेशन्स् स्प्रिंग् अस्माकं कृते लेनदेनप्रबन्धनं कर्तुं अनुमतिं ददति, यथा अपवादक्रियाणां रोल बैक् करणं, पुनरावृत्तिव्यवहारप्रबन्धनतर्कं समाप्तं करोति ।@Transactional
एओपी इत्यस्य आधारेण एनोटेशन्स् कार्यान्विताः भवन्ति ।
अनुमतिनियन्त्रणम् : लक्ष्यविधिं निष्पादयितुं पूर्वं उपयोक्तुः आवश्यकाः अनुमतिः अस्ति वा इति निर्धारयितुं AOP इत्यस्य उपयोगं कुर्वन्तु यदि अस्ति तर्हि लक्ष्यविधिं निष्पादयन्तु, अन्यथा सा निष्पादयिष्यति ।यथा, SpringSecurity इत्यस्य उपयोगं करोति@PreAuthorize
कोडपङ्क्तिं टिप्पणीं कृत्वा अनुमतिसत्यापनं अनुकूलितुं शक्नुवन्ति ।
अन्तरफलकवर्तमानसीमाकरणम् : लक्ष्यपद्धतेः निष्पादनात् पूर्वं विशिष्टवर्तमानसीमाकरण एल्गोरिदम्स् तथा कार्यान्वयनद्वारा अनुरोधं सीमितुं AOP इत्यस्य उपयोगं कुर्वन्तु ।
Cache management: लक्ष्यपद्धतेः निष्पादनात् पूर्वं पश्चात् च cache पठितुं अद्यतनीकर्तुं च AOP इत्यस्य उपयोगं कुर्वन्तु ।
एओपी इत्यस्य सामान्यकार्यन्वयनविधयः गतिशीलप्रॉक्सी, बाइटकोड्सञ्चालनम् इत्यादयः सन्ति ।
Spring AOP गतिशीलप्रॉक्सी इत्यस्य आधारेण भवति यदि प्रॉक्सी कर्तव्यं वस्तु निश्चितं अन्तरफलकं कार्यान्वितं करोति तर्हि Spring AOP इत्यस्य उपयोगं करिष्यति जेडीके प्रॉक्सी, प्रॉक्सी-वस्तु निर्मातुं ये वस्तुनः अन्तरफलकं कार्यान्वितुं न शक्नुवन्ति, तेषां कृते प्रॉक्सी-करणाय भवान् JDK Proxy इत्यस्य उपयोगं कर्तुं न शक्नोति Cglib प्रॉक्सीरूपेण कार्यं कर्तुं प्रॉक्सी-वस्तुनः उपवर्गं जनयन्तु
अस्तिspring-aop.xml
विन्याससञ्चिकायां सम्बन्धितबीन्स् तथा पक्षाः विन्यस्यताम्
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
-
- <bean id="target" class="com.xxhh.aopdemo.aop.Target"/>
-
- <bean id="targetAdvice" class="com.xxhh.aopdemo.aop.TargetAdvice"/>
-
- <bean id="targetProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
- <property name="target" ref="target"/> <!--被代理的类-->
- <property name="interceptorNames" value="targetAdvice"/> <!--如果用多种增强方式,value的值使用逗号(,)分割-->
- <property name="proxyTargetClass" value="false"/> <!--如果设置为true,则创建基于类的代理(使用CGLIB);如果设置为false,则创建基于接口的代理(使用JDK动态代理)。-->
- <property name="interfaces" value="com.xxhh.aopdemo.aop.TargetInteface"/> <!--target实现的接口-->
- </bean>
- </beans>
- public interface TargetInteface {
- void method1();
- void method2();
- int method3(Integer i);
- }
- public class Target implements TargetInteface{
-
- /*
- * 需要增强的方法,连接点JoinPoint
- **/
- @Override
- public void method1() {
- System.out.println("method1 running ...");
- }
-
- @Override
- public void method2() {
- System.out.println("method2 running ...");
- }
-
- @Override
- public int method3(Integer i) {
- System.out.println("method3 running ...");
- return i;
- }
- }
- public class TargetAdvice implements MethodInterceptor, MethodBeforeAdvice, AfterReturningAdvice {
-
- /*
- * 通知/增强
- **/
- @Override
- public Object invoke(MethodInvocation methodInvocation) throws Throwable {
- System.out.println("前置环绕通知");
- Object proceed = methodInvocation.proceed();
- System.out.println("后置环绕通知");
- return proceed;
- }
-
- @Override
- public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
- System.out.println("后置返回通知");
- }
-
- @Override
- public void before(Method method, Object[] args, Object target) throws Throwable {
- System.out.println("前置通知");
- }
- }
- public class AopTest {
- public static void main(String[] args) {
- ApplicationContext appCtx = new ClassPathXmlApplicationContext("spring-aop.xml");
- TargetInteface targetProxy = (TargetInteface) appCtx.getBean("targetProxy");
- targetProxy.method1();
- }
- }
आउटपुट् परिणामः : १.
अग्रसूचना परिवेश
पूर्वसूचना
विधि1 चालयन् ...
post return notification
पृष्ठतः अधिसूचना परिवेश
अस्तिspring-confaop.xml
विन्याससञ्चिकायां सम्बन्धितबीन्स् तथा पक्षाः विन्यस्यताम्
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
-
- <!--先开启cglib代理,开启 exposeProxy = true,暴露代理对象-->
- <aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>
- <!--扫包-->
- <context:component-scan base-package="com.xxhh.aopdemo.annotationaop"/>
-
- </beans>
- /*
- * 目标类
- **/
- public class Target {
-
- public void method1() {
- System.out.println("method1 running ...");
- }
-
- public void method2() {
- System.out.println("method2 running ...");
- }
-
- /*
- * 连接点JoinPoint
- **/
- public int method3(Integer i) {
- System.out.println("method3 running ...");
- // int i1 = 1 / i;
- return i;
- }
- }
- import org.aspectj.lang.ProceedingJoinPoint;
- /*
- * 切面类
- **/
- public class TargetAspect {
-
- /*
- * 前置通知
- **/
- public void before() {
- System.out.println("conf前置通知");
- }
-
- public void after() {
- System.out.println("conf后置通知");
- }
-
- public void afterReturning() {
- System.out.println("conf后置返回通知");
- }
-
- public void afterThrowing(Exception ex) throws Exception {
- // System.out.println("conf异常通知");
- // System.out.println(ex.getMessage());
- }
-
- public Object around(ProceedingJoinPoint pjp) throws Throwable {
- Object proceed = null;
- if (!"".equals("admin")) {
- System.out.println("conf环绕前置");
- proceed = pjp.proceed(pjp.getArgs());
- System.out.println("conf环绕后置");
- }
- return proceed;
- }
- }
- public class AopTest {
- public static void main(String[] args) {
- ApplicationContext appCtx = new ClassPathXmlApplicationContext("spring-confaop.xml");
- Target targetProxy = (Target) appCtx.getBean("target");
- System.out.println(targetProxy.method3(0));
- }
- }
आउटपुट् परिणामः : १.
conf पूर्वसूचना
conf परितः उपसर्गः
विधि३ चालयन् ...
conf प्रत्यागमनोत्तर सूचना
conf surround post
conf पोस्ट सूचना
0
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
-
- <!--先开启cglib代理,开启 exposeProxy = true,暴露代理对象-->
- <aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>
- <!--扫包-->
- <context:component-scan base-package="com.xxhh.aopdemo.annotationaop"/>
-
- </beans>
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- public @interface TestAnnotation{
- }
- /*
- * 切面类
- **/
- @Aspect
- @Component
- public class AnnotationAspect {
-
- // 定义一个切点:所有被RequestMapping注解修饰的方法会织入advice
- @Pointcut("@annotation(TestAnnotation)")
- private void advicePointcut() {}
-
- /*
- * 前置通知
- **/
- @Before("advicePointcut()")
- public void before() {
- System.out.println("annotation前置通知");
- }
-
- @After("advicePointcut()")
- public void after() {
- System.out.println("annotation后置通知");
- }
-
- @AfterReturning(pointcut = "advicePointcut()")
- public void afterReturning() {
- System.out.println("annotation后置返回通知");
- }
-
- @AfterThrowing(pointcut = "advicePointcut()", throwing = "ex")
- public void afterThrowing(Exception ex) throws Exception {
- System.out.println("annotation异常通知");
- System.out.println(ex.getMessage());
- }
-
- @Around("advicePointcut()")
- public Object around(ProceedingJoinPoint pjp) throws Throwable {
- Object proceed = null;
- if (!"".equals("admin")) {
- System.out.println("annotation环绕前置");
- proceed = pjp.proceed(pjp.getArgs());
- System.out.println("annotation环绕后置");
- }
- return proceed;
- }
- }
- @Controller
- public class TestController {
-
- @RequestMapping("/test.do")
- @ResponseBody
- public String testController() {
- TestController o = (TestController) AopContext.currentProxy();
- o.test();
- // System.out.println("tewt");
- return "ok";
- }
-
- @TestAnnotation
- public void test() {
- System.out.println("test running");
- }
-
- }