سؤال

أقوم بإنشاء وكلاء باستخدام javassist ProxyFactory.عند إنشاء وكيل واحد كل شيء يعمل بشكل جيد.

ومع ذلك، عندما أقوم بتمرير كائن وكيل إلى آلية الوكيل، فإنه يفشل

javassist.bytecode.DuplicateMemberException:طريقة مكررة:setHandler في com.mypackage.Bean_$$_javassist_0_$$_javassist_1

أقوم بإنشاء الوكلاء بهذا:

public Object createProxiedInstance(Object originalInstance) throws Exception {
    Class<?> originalClass = instance.getClass();
    ProxyFactory factory = new ProxyFactory();

    factory.setSuperclass(originalClass);

    factory.setHandler(new MethodHandler() {..});
    Class<T> proxyClass = factory.createClass();

    return proxyClass.newInstance();
}

إذًا، كيف يمكنني إنشاء وكلاء للوكلاء؟

تحديث: المشكلة الفعلية هي أن كل وكيل ينفذ ProxyObject الذي يحدد setHandler(..) طريقة.لذا يحاول الوكيل الثاني إعادة تعريف الطريقة، بدلاً من تجاوزها في الفئة الفرعية.

هل كانت مفيدة؟

المحلول

كانت المشكلة (في الواقع ، هي نفسها مع CGLIB - لقد جربتها باستخدام العموم بوكسي) أنني لا ينبغي أن أحاول إنشاء فئة وكيل من فئة الوكيل. يجب أن يكون الوكيل الثاني مرة أخرى من الفصل الأصلي. لذا فإن إضافة السطر التالي يحل المشكلة:

if (instance instanceof ProxyObject) {
    originalClass = originalClass.getSuperclass();
}

ونصيحة - إذا كان يمكنك استخدام نوع من التقاطعات (مثل تلك المحددة في العموم -بوكسي) ، فقم بذلك بدلاً من استخدام وكلاء متعددة.

نصائح أخرى

إنها إجابة متأخرة إلى حد ما ولكن ربما لا تزال مهتمًا بمعرفة هذا:

يتم تنفيذ وكلاء Javassist بسذاجة إلى حد ما.في الكود أعلاه، سيقوم Javassist دائمًا بإنشاء فئة وكيل بالطرق التالية:

  1. طريقة لأي طريقة يمكن تجاوزها للفئة الأساسية
  2. طريقتان لـ (أ) الحصول على معالج الوكيل (getHandler) و (ب) تعيين معالج الوكيل (setHandler)

يتم ترميز أسماء الطريقتين الأخيرتين بواسطة Javassist ويتم تمثيلهما بـ ProxyObject واجهه المستخدم.إذا قمت الآن بإنشاء فئة وكيل لفئة وكيل، فسيقوم Javassist بجدولة إنشاء ProxyObjectطرق مرتين.مرة بالشرط الأول ومرة ​​بالشرط الثاني.

يمكنك تجنب ذلك عن طريق تعيين أ MethodFilter الذي يحدد عدم تجاوز ProxyObjectأساليب بحيث يقوم javassist بإنشاء الأساليب فقط حسب الشرط الثاني.ومع ذلك، فإن هذا يعني أنه لم يعد بإمكانك تعيين ملف ProxyObject لوكيل الفئة الفائقة دون الوصول مباشرة إلى الحقل المقابل عبر الانعكاس.لذلك، ربما يكون نهجك هو الأنظف.

يحدد cglib عمليات الاسترجاعات لكل فئة وليس لكل مثيل، بحيث تكون مشكلة cglib مختلفة قليلاً ولكنها تؤدي إلى تعارض آخر.

ومع ذلك، إذا كنت ترغب في إنشاء فئات وكيل لا تعاني من هذه العيوب، فقد تكون مهتمًا بمكتبتي بايت الأصدقاء الذي كتبته بعد أن شعرت بالإحباط من العمل مع cglib وjavassist عند العمل في الحالات الزاوية.إذا كنت تعمل مع إنشاء التعليمات البرمجية في وقت التشغيل، آمل أن يساعدك ذلك في توفير بعض المرونة التي تفتقر إليها المكتبات الأخرى.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top