ما هو AOP
يمكن القول أن AOP (البرمجة الموجهة نحو الجانب ، والبرمجة الموجهة نحو الجانب) هي ملحق وتحسين OOP (البرمجة الموجهة للكائنات). يقدم OOP مفاهيم مثل التغليف والميراث وتعدد الأشكال لإنشاء تسلسل هرمي كائن لمحاكاة مجموعة من السلوكيات العامة. عندما نحتاج إلى إدخال السلوك العام للأشياء المتناثرة ، يبدو OOP عاجزًا. أي أن OOP يتيح لك تحديد العلاقات من أعلى إلى أسفل ، ولكنه غير مناسب لتحديد العلاقات من اليسار إلى اليمين. على سبيل المثال ، وظيفة التسجيل. غالبًا ما يكون رمز السجل مبعثرًا أفقيًا عبر جميع مستويات الكائنات دون أي علاقة بالوظائف الأساسية للكائن الذي ينتشر إليه. وينطبق الشيء نفسه على الأنواع الأخرى من التعليمات البرمجية ، مثل الأمان ومعالجة الاستثناءات والشفافية. هذا النوع من الكود غير ذي صلة المبعثر في كل مكان يسمى رمز قطع المتقاطع. في تصميم OOP ، يسبب الكثير من تكرار الكود ، والذي لا يفضي إلى إعادة استخدام كل وحدة.
مقدمة
نمط تصميم جافا الذي كتبته منذ بعض الوقت - نمط الوكيل. في الآونة الأخيرة ، عندما كنت أنظر إلى الربيع AOP ، شعرت أنه يجب أن تكون هناك اتصالات وثيقة في نمط الوكيل ، لذلك قررت أن أفهم مبدأ التنفيذ في الربيع AOP.
الحديث عن AOP ، علينا أن نتحدث عن OOP. يتم تقديم مفاهيم التغليف والميراث وتعدد الأشكال في OOP لإنشاء تسلسل هرمي كائن لمحاكاة مجموعة من السلوكيات العامة. ومع ذلك ، إذا كنا بحاجة إلى تقديم أجزاء مشتركة لبعض الكائنات ، فسيقدم OOP الكثير من التعليمات البرمجية المكررة. على سبيل المثال: وظيفة التسجيل.
تستخدم تقنية AOP تقنية تسمى "crosscutting" لتشريح داخل الكائن المغطى وتغليف السلوكيات الشائعة التي تؤثر على فئات متعددة في وحدة قابلة لإعادة الاستخدام ، والتي يمكن أن تقلل من تكرار النظام في الكود ، وتقليل الاقتران بين الوحدات النمطية ، وتسهيل عملية التشغيل والصيانة في المستقبل. يقسم AOP نظام البرمجيات إلى جزأين: القلق الأساسي والاهتمام المتقاطع. العملية الرئيسية لمعالجة الأعمال هي التركيز الأساسي ، والجزء الذي لا علاقة له به هو التركيز المستعرض. تتمثل إحدى خصائص المخاوف المتقاطعة في أنها تحدث في كثير من الأحيان في مخاوف متعددة ، وتشبه بشكل أساسي في كل مكان. على سبيل المثال ، مصادقة الإذن وتسجيلها ومعالجة المعاملات.
مبدأ التنفيذ
عندما كنت أتعلم وضع الوكيل ، علمت أن وضع الوكيل ينقسم إلى وكيل ديناميكي وكيل ثابت. الآن سنقوم أولاً بتنفيذ إطار عمل AOP الخاص بنا بناءً على نموذج الوكيل ، ثم ندرس مبادئ تنفيذ AOP في Spring.
أولاً ، يتم تنفيذها باستخدام وكيل ثابت. يتمثل مفتاح الوكيل الثابت في تنفيذ واجهة مشتركة بين كائن الوكيل والكائن الهدف ، ويحمل كائن الوكيل مرجعًا إلى الكائن الهدف.
رمز الواجهة العامة:
الواجهة العامة ihello {/*** طريقة العمل*param str*/void sayhello (String str) ؛} رمز الفئة الهدف: Hello class public yehello {overridepublic void sayhello (String str) {system.out.println ("hello"+str) ؛}}}}}}}}}}} بالنسبة إلى رمز فئة الوكيل ، نضيف وظيفة التسجيل إليها ، وننفذ طرقًا محددة قبل وبعد بدء الطريقة. أليس هذا مشابهًا بشكل خاص لـ AOP؟
proxyhello الطبقة العامة تنفذ ihello {private ihello hello ؛ proxyhello العامة (ihello hello) {super () ؛ this.hello = hello ؛}@overridepublic void sayhello (String str) {logger.start () ؛ // إضافة طريقة محددة hello.sayhello (str) ؛ logger.end () ؛}} رمز فئة السجل:
logger الفئة العامة {public static void start () {system.out.println (new date ()+ "say hello start ...") ؛} end static static end () {system.out.println (new date ()+ "say hello end") ؛}}}}}} رمز الاختبار:
اختبار الفئة العامة {public static void main (string [] args) {ihello hello = new proxyhello (new hello ()) ؛ // إذا كنا بحاجة إلى وظيفة تسجيل الدخول ، فاستخدم فئة الوكيل // ihello hello = new hello () ؛ // إذا لم نحتاج إلى وظيفة تسجيل ، فاستخدم فئة الهدف hell.sayhello ("الغد") ؛ }}وبهذه الطريقة ، نقوم بتنفيذ أبسط AOP ، ولكن ستكون هناك مشكلة: إذا كان لدينا العديد من الفصول مثل Hello ، فهل يجب أن نكتب العديد من الفصول مثل Helloproxy؟ في الواقع ، إنه أيضًا شيء مزعج للغاية. بعد JDK1.3 ، يزودنا JDK بفئة API java.lang.reflect.invocationHandler. يتيح لنا هذه الفئة القيام بشيء ما لبعض الطرق عندما يستدعي JVM طرق فئة معينة. دعنا ننفذ تنفيذ الوكيل الديناميكي.
ينفذ تنفيذ الوكيل الديناميكي بشكل أساسي ، ويحقق الكائن الهدف في الكائن الوكيل ، باستخدام آلية الانعكاس لتنفيذ طريقة الكائن الهدف.
تطبيق الواجهة هو نفسه الوكيل الثابت ، رمز فئة الوكيل:
الفئة العامة dynaproxyhello تنفذ invocationHandler {target الكائن الخاص // الكائن الهدف/*** إنشاء الكائن الهدف من خلال الانعكاس* param object* @return*/public object bind (object) {this.target = object ؛ this.target.getClass (). getInterfaces () ، هذا) ؛}@@overridepublic كائن استدعاء (وكيل الكائن ، طريقة الطريقة ، الكائن [] args) يلقي رمي {كائن نتيجة = null ؛ logger.start () رمز فئة الاختبار:
الطبقة العامة dynatest {public static void main (string [] args) {ihello hello = (iHello) New Dynaproxyhello (). bind (new hello ()) ؛ // إذا كنا نتعامل مع وظيفة التسجيل ، استخدم فئة الوكيل // ihell hello = new hello () ؛ بعد قراءة الكود أعلاه ، قد تكون هناك مشكلة مقارنة بـ Spring AOP. لا يمكن طباعة فئة السجل إلا قبل وبعد الطريقة ، ولكن يجب أن تكون AOP قادرة على التنفيذ عند استيفاء الشروط. هل يمكن فصل كل كائن Dynapoxyhello وكائن تشغيل السجل (المسجل)؟
بالنظر إلى تطبيق الكود التالي ، سوف يفصل كائن Dynapoxyhello وكائن تشغيل السجل (المسجل):
نحتاج إلى إضافة رمز تشغيل السجل (أو رمز التشغيل الآخر) قبل أو بعد طريقة كائن الوكيل. بعد ذلك ، يمكننا تجريد واجهة ، والتي تحتوي على طريقتين فقط: واحدة هي الطريقة التي يتم تنفيذها قبل أن يريد كائن الوكيل تنفيذ الطريقة. قمنا بتسميته ، والطريقة الثانية هي الطريقة التي تم تنفيذها بعد تنفيذ كائن الوكيل بالطريقة ، وقمنا بتسميةها.
واجهة Logger:
الواجهة العامة ilogger {void start (طريقة طريقة) ؛ نهاية الفراغ (طريقة الطريقة) ؛} تطبيق واجهة المسجل:
الطبقة العامة dlogger تنفذ ilogger {OverRidepublic Void start (طريقة طريقة) {system.out.println (date new () + method.getName () + "say hello start ...") فئة الوكيل الديناميكي:
الفئة العامة dynaproxyhello تنفذ invocationHandler {// كائن استدعاء كائن خاص بروكسي ؛ // الهدف الكائن الهدف الكائن الخاص ؛ ربط الكائن العام (الهدف الكائن ، وكيل الكائن) {this.target = target ؛ this.proxy = proxy ؛ return proxy.newproxyinstance (this.target.getClass (). this.target.getClass (). getInterfaces () ، هذا) ؛}@@overridepublic كائن استدعاء (وكيل الكائن ، طريقة الطريقة ، الكائن [] args) رمي {كائن نتيجة = null ؛ class [] {method.class}) ؛ // ينفذ الانعكاس طريقة البدء start.invoke (this.proxy ، كائن جديد [] {this.proxy.getclass ()}) ؛ // ينفذ الطريقة الأصلية لمعالجة طريقة الكائن. Class [] {method.class}) ؛ // ينفذ الانعكاس طريقة النهاية end.invoke (this.proxy ، كائن جديد [] رمز الاختبار:
الطبقة العامة dynatest {public static void main (string [] args) {ihello hello = (ihello) new Dynaproxyhello (). bind (new hello () ، new dlogger ()) ؛ Hello.sayhello ("الغد") ؛}} من خلال المثال أعلاه ، يمكننا أن نجد أنه من خلال تقنية البرامج والبلاط الديناميكي ، تم تنفيذ وظيفة AOP بشكل أساسي. إذا كنا بحاجة فقط إلى طباعة السجل قبل تنفيذ الطريقة ، لا يمكننا تنفيذ طريقة النهاية () ، حتى نتمكن من التحكم في توقيت الطباعة. إذا كنا نريد أن تقوم الطريقة المحددة بطباعة السجل ، فنحن بحاجة فقط إلى إضافة حكم على اسم الطريقة إلى طريقة Invoke (). يمكن كتابة اسم الطريقة في ملف XML ، حتى نتمكن من فصله باستخدام ملف التكوين ، بحيث ننفذ إطارًا بسيطًا لـ Spring AOP.
المحتوى أعلاه هو مبدأ تنفيذ الربيع AOP الذي قدمه لك المحرر. آمل أن يكون ذلك مفيدًا لك!