في المقالة السابقة ، قمنا بتحليل كيفية إنشاء فئة الوكيل داخل فئة الوكيل. رأينا أن آلية ذاكرة التخزين المؤقت تستخدم داخل الوكيل. إذا كان من الممكن العثور على فئة الوكيل في ذاكرة التخزين المؤقت بناءً على مجموعة محمل الفئة المقدمة ومجموعة الواجهة ، فسيتم إرجاع فئة الوكيل مباشرة. خلاف ذلك ، سيتم استدعاء مصنع proxyclassfactory لإنشاء فئة الوكيل. ذاكرة التخزين المؤقت المستخدمة هنا هي ذاكرة التخزين المؤقت الثانوية ، ويتم إنشاء مفتاح ذاكرة التخزين المؤقت من المستوى الأول بناءً على محمل الفئة ، ويتم إنشاء مفتاح ذاكرة التخزين المؤقت من المستوى الثاني بناءً على صفيف الواجهة. سنقوم بنشر الكود مباشرة لشرح الآلية الداخلية المحددة بالتفصيل.
// قائمة انتظار مرجعية مرجعية خاصة مرجعية نهائية <K> refqueue = new ReferenceQueue <> () ؛ // التنفيذ الأساسي للذاكرة التخزين المؤقت ، يكون المفتاح هو ذاكرة التخزين المؤقت من المستوى الأول والقيمة هي ذاكرة التخزين المؤقت من المستوى الثاني. من أجل دعم NULL ، يتم تعيين نوع المفتاح من الخريطة على CONFORTPRINCE FINDAL CONSURRENTMAP <كائن ، CONCURRENTMAP <Object ، المورد <v>> map = concurrenthashmap new concurrenthashmap <> () ؛ // REVERSEMAP يسجل ما إذا كانت جميع مولدات فئة الوكيل متوفرة. هذا هو تنفيذ آلية انتهاء ذاكرة التخزين المؤقت الخاصة النهائية الخاصة بالتزامن مع المورد <v> ، boolean> respertemap = جديد concurrenthashmap <> () bifunction <k ، p ، v> valuefactory ؛ // constructor ، المصنع الذي يولد مفتاح ذاكرة التخزين المؤقت الثانوي والمصنع الذي يولد قيمة ذاكرة التخزين المؤقت الثانوية الضعيفة (bifunction <k ، p ،؟> subkeyfactory ، bifunction <k ، p ، v> valuefactory) {this.subkeyfactory = this.valuefactory = objects.requirenonnull (valuefactory) ؛}أولاً ، دعنا نلقي نظرة على متغيرات الأعضاء ومُنشئ PreamCache. يتم الانتهاء من التنفيذ الداخلي لذاكرة التخزين المؤقت للضعف من خلال ConcurrentMap. الخريطة المتغيرة العضو هي التنفيذ الأساسي للذاكرة التخزين المؤقت الثانوية. REVERSEMAP هو تنفيذ آلية انتهاء صلاحية ذاكرة التخزين المؤقت. Subkeyfactory هو مصنع توليد مفتاح ذاكرة التخزين المؤقت الثانوية. يتم تمريره من خلال المنشئ. القيمة التي تم تمريرها هنا هي keyfactory لفئة الوكيل ، والقيمة هي مصنع توليد قيمة ذاكرة التخزين المؤقت الثانوية. يتم تمريره من خلال المنشئ. يتم تمرير ProxyClassFactory من فئة الوكيل هنا. بعد ذلك ، دعونا نلقي نظرة على طريقة Get of PeactCache.
public v get (k key ، p parameter) {// الواجهة المطلوبة لتنفيذها هنا لا يمكن أن تكون كائنات فارغة . // classloader في cachekey كمفتاح ل cachekey من مستوى ذاكرة التخزين المؤقت من المستوى الأول = cachekey.valueof (المفتاح ، refqueue) ؛ // احصل على ذاكرة التخزين المؤقت الثانوية ConcurrentMap <object ، المورد <v>> valuesmap = map.get (cachekey) ؛ // إذا لم يتم الحصول على القيمة المقابلة استنادًا إلى classloader if (dordermap == null) {// ضعها في CAS ، إذا لم تكن موجودة ، فضعها في ، وإلا إلى القيمة الأصلية concurrentMap <object ، المورد <v>> oldvaluesmap = map.putifabsent (cachekey ، datemap = new concurrenthashmap <>) ؛ // إذا كان لدى OldValuesMap قيمة ، فهذا يعني أن الموضع فشل إذا (oldvaluesmap! = null) {valuesmap = oldvaluesmap ؛ }} // قم بإنشاء مفتاح ذاكرة التخزين المؤقت من المستوى الثاني استنادًا إلى صفيف الواجهة الذي تم تنفيذه بواسطة فئة الوكيل ، مقسومًا إلى key0 ، key1 ، key2 ، keyx object subkey = objects.requirenonnull (subkeyfactory.apply (المفتاح ، المعلمة)) ؛ // يتم الحصول على قيمة ذاكرة التخزين المؤقت الثانوية من خلال المفتاح الفرعي. المورد <v> المورد = قيم map.get (مفتاح subkey) ؛ مصنع المصنع = فارغ ؛ // توفر هذه الحلقة آلية اقتراع. إذا كانت الحالة خاطئة ، فاستمر في المحاولة مرة أخرى حتى يكون الشرط صحيحًا بينما (صحيح) {// إذا كانت القيمة التي تم استردادها من خلال المفتاح الفرعي ليست فارغة إذا كان (المورد! = null) {// قد يكون العرض مصنعًا أو cachevalue // لم يتم إصدار حكم هنا ، ولكن التحقق من طريقة الحصول على فئة تنفيذ المورد V value.get () ؛ if (value! = null) {return value ؛ }} if (Factory == NULL) {// إنشاء مثيل مصنع جديد كقيمة مقابلة لمصنع المفتاح الفرعي = مصنع جديد (مفتاح ، المعلمة ، المفتاح الفرعي ، القيم) ؛ } if (المورد == null) {// هنا يعني أن المفتاح الفرعي ليس له قيمة مقابلة ، وضع المصنع كقيمة للمفتاح الفرعي في المورد = قيم map.putifabsent (المفتاح الفرعي ، المصنع) ؛ إذا (المورد == null) {// ، فهذا يعني أن المصنع يتم وضعه بنجاح في مورد ذاكرة التخزين المؤقت = المصنع ؛ } // خلاف ذلك ، قد تعدل مؤشرات الترابط الأخرى القيمة خلال الفترة ، ثم لم نعد نستمر في تعيين قيم للمفتاح الفرعي ، ولكن أخرجها واستخدامها مباشرة} {// خلال هذه الفترة ، قد تكون مؤشرات الترابط الأخرى قد تعديل القيمة ، لذلك استبدل القيمة الأصلية إذا (datemap.replace (Subkey ، المورد ، المورد)) } آخر {// استبدال فشل ، تابع استخدام المورد الأصلي للقيمة = valueMap.get (مفتاح subke) ؛ }}}}لا تتم مزامنة طريقة GET DefelCache مع الأقفال ، فكيف تحقق سلامة الخيط؟ نظرًا لأن جميع متغيرات الأعضاء المعدلة تستخدم ConcurrentMap ، فإن هذه الفئة آمنة مؤشرات الخيط. لذلك ، فإنه يولد سلامة مؤشرات الترابط الخاصة به إلى ConcurrentMap ، وتقلل طريقة GET من كتل رمز التزامن قدر الإمكان ، والتي يمكن أن تحسن بشكل فعال من أداء الضعيف. نرى أن ClassLoader هو مفتاح ذاكرة التخزين المؤقت من المستوى 1 ، حتى نتمكن من تصفيةه أولاً وفقًا لـ ClassLoader ، لأن الفئات التي يتم تحميلها بواسطة قائدي فئة مختلفة مختلفة. ثم يستخدم صفيف واجهة لإنشاء مفتاح ذاكرة التخزين المؤقت الثانوية. هنا لديه بعض التحسينات. نظرًا لأن معظم الفئات تنفذ واجهتين أو واجهتين ، يتم تقسيم مفتاح ذاكرة التخزين المؤقت الثانوية إلى key0 و key1 و key2 و keyx. يعني Key0 to Key2 أنه يتم تنفيذ واجهات من 0 إلى 2 ، ويعني Keyx أنه يتم تنفيذ 3 واجهات أو أكثر. في الواقع ، سوف يستخدم معظمهم فقط key1 و key2. يوجد مصنع توليد هذه المفاتيح في فئة الوكيل ، ويتم تمرير المصنع الرئيسي من خلال مُنشئ ComeChe. قيمة ذاكرة التخزين المؤقت من المستوى الثاني هنا هي مثيل للمصنع ، ويتم الحصول على القيمة النهائية لفئة الوكيل من خلال مصنع المصنع.
يقوم مصنع الفصل النهائي الخاص بتنفيذ المورد <v> {// المستوى 1 مفتاح ذاكرة التخزين المؤقت ، قم بإنشاء مفتاح K النهائي الخاص وفقًا لـ ClassLoader ؛ // واجهة صفيف المعلمة P الخاصة Prameter التي تنفذها فئة الوكيل ؛ // مفتاح ذاكرة التخزين المؤقت من المستوى 2 ، قم بإنشاء مفتاح Subse الخاص بكائن نهائي خاص وفقًا لصفيف الواجهة ؛ // المستوى 2 ذاكرة التخزين المؤقت الخاصة ConcurrentMap <object ، المورد <v>> قيم map ؛ المصنع (مفتاح k ، p المعلمة ، مفتاح الكائن الفرعي ، concurrentMap <object ، المورد <v >> قيم map) {this.key = key ؛ this.parameter = المعلمة ؛ this.subkey = المفتاح الفرعي ؛ this.valuesmap = valuesmap ؛ } Override Public Synchronized v get () {// هنا أذهب إلى ذاكرة التخزين المؤقت الثانوية مرة أخرى للحصول على المورد للتحقق مما إذا كان المصنع نفسه مورد <v> المورد = valueMap.get (subkey) ؛ إذا كان (المورد! = هذا) {// هنا ، أتحقق مما إذا كان المورد هو مثيل المصنع نفسه ، إن لم يكن ، إرجاع فارغ ودع المتصل يستمر في الاستطلاع وإعادة المحاولة // خلال الفترة ، يمكن استبدال المورد بـ cachevalue ، أو تتم إزالته من ذاكرة التخزين المؤقت الثانوية بسبب الإخفاق في توليد فئة الوكيل ؛ } v value = null ؛ جرب {// تفويض القيمة لإنشاء فئة الوكيل ، وهنا سيتم إنشاء قيمة فئة الوكيل من خلال proxyclassfactory = objects.requirenonnull (valuefactory.apply (المفتاح ، المعلمة)) ؛ } أخيرًا {// في حالة فشل توليد فئة الوكيل ، قم بحذف ذاكرة التخزين المؤقت الثانوية إذا كانت (value == null) {valuesmap.remove (مفتاح subke ، هذا) ؛ }} // فقط قيمة القيمة ليست فارغة ، هل يمكن أن تصل هنا إلى تأكيد القيمة! = null ؛ . // ضع cachevalue المعبأة في ذاكرة التخزين المؤقت الثانوية. يجب أن تكون هذه العملية ناجحة ، وإلا سيتم الإبلاغ عن خطأ إذا كان (dordermap.replace (مفتاح subke ، هذا ، cachevalue)) {// بعد وضع cachevalue بنجاح في ذاكرة التخزين المؤقت الثانوية ، وضع علامة على reversemap.put (cachevalue ، boolean.true) ؛ } آخر {رمي تأكيد جديد ("يجب ألا تصل إلى هنا") ؛ } // أخيرًا إرجاع قيمة إرجاع فئة الوكيل التي لا يتم لفها بمرجع ضعيف ؛ }}دعونا نلقي نظرة على مصنع فئة المصنع الداخلي مرة أخرى ، ويمكننا أن نرى أن طريقة الحصول عليها تتم مزامنتها باستخدام الكلمة الرئيسية المتزامنة. بعد أداء طريقة GET ، تحقق أولاً مما إذا كان المورد المقابل للمفتاح الفرعي هو المصنع نفسه. إذا لم يكن الأمر كذلك ، فسوف يعود NULL ، وسوف تستمر طريقة GET DEFCACHE في المحاولة مرة أخرى. إذا كان المصنع نفسه بالفعل ، فسيتم تفويض ProxyClassFactory لإنشاء فئة الوكيل ، والتي يتم تمريرها عند بناء Confcache. لذا ، يشرح هنا سبب استدعاء المصنع الداخلي لـ ProxyClassFactory في الوكيل لإنشاء فئة الوكيل في النهاية. بعد إنشاء فئة الوكيل ، يستخدم مرجعًا ضعيفًا للفه ووضعه في ResperSeMap ، ويعيد أخيرًا فئة الوكيل الأصلية.
حتى الآن ، كشفنا بالتفصيل عن تنفيذ ذاكرة التخزين المؤقت للضعف ، بما في ذلك ذاكرة التخزين المؤقت من المستوى الأول ومبادئ تنفيذ ذاكرة التخزين المؤقت من المستوى الثاني ، بالإضافة إلى مبدأ إنشاء مفتاح ذاكرة التخزين المؤقت من المستوى الثاني ، وكيفية استدعاءها لتوليد فئة الوكيل في النهاية. في المقالة التالية ، سنذهب إلى فئة ProxyGenerator لمشاهدة عملية توليد Bytecode لفئة الوكيل المحددة.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.