বিমূর্ত শ্রেণীর প্রক্সি তৈরি করার জন্য java.lang.reflect.Proxy এর বিকল্প (ইন্টারফেসের পরিবর্তে)


90

ডকুমেন্টেশন অনুযায়ী :

[ java.lang.reflect.] Proxyগতিশীল প্রক্সি ক্লাস এবং দৃষ্টান্তগুলি তৈরি করার জন্য স্থির পদ্ধতি সরবরাহ করে এবং এটি সেই পদ্ধতিগুলির দ্বারা তৈরি সমস্ত গতিশীল প্রক্সি ক্লাসের সুপারক্লাস।

newProxyMethodপদ্ধতি (গতিশীল প্রক্সি জেনারেট করার জন্য দায়ী) নিম্নলিখিত স্বাক্ষর রয়েছে:

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
                             throws IllegalArgumentException

দুর্ভাগ্যবশত, একটি গতিশীল প্রক্সি যে উৎপাদিত থেকে বাধা দেয় এক প্রসারিত (বদলে একটি নির্দিষ্ট বিমূর্ত বর্গ বাস্তবায়নে নির্দিষ্ট ইন্টারফেস)। এটি বোঝা যায়, java.lang.reflect.Proxy"সমস্ত গতিশীল প্রক্সিগুলির সুপারক্লাস" বিবেচনা করে এটি অন্য শ্রেণিকে সুপারক্লাস হতে বাধা দেয়।

সুতরাং, এর জন্য এমন কোনও বিকল্প আছে java.lang.reflect.Proxyযেগুলি গতিশীল প্রক্সি তৈরি করতে পারে যা একটি নির্দিষ্ট বিমূর্ত শ্রেণীর উত্তরাধিকার সূত্রে প্রাপ্ত, বিমূর্ত পদ্ধতিতে সমস্ত কলগুলি ডাকে হস্তান্তরকারীকে পুনর্নির্দেশ করে ?

উদাহরণস্বরূপ, ধরুন আমার একটি বিমূর্ত শ্রেণি রয়েছে Dog:

public abstract class Dog {

    public void bark() {
        System.out.println("Woof!");
    }

    public abstract void fetch();

}

এমন কোন শ্রেণি রয়েছে যা আমাকে নিম্নলিখিতগুলি করতে অনুমতি দেয়?

Dog dog = SomeOtherProxy.newProxyInstance(classLoader, Dog.class, h);

dog.fetch(); // Will be handled by the invocation handler
dog.bark();  // Will NOT be handled by the invocation handler

উত্তর:


123

এটি জাভাসিস্ট (দেখুন ProxyFactory) বা সিজিএলআইবি ব্যবহার করে করা যেতে পারে ।

জাভাসিস্ট ব্যবহার করে আদমের উদাহরণ:

আমি (অ্যাডাম পেইন্টার) জাভাসিস্ট ব্যবহার করে এই কোডটি লিখেছি:

ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(Dog.class);
factory.setFilter(
    new MethodFilter() {
        @Override
        public boolean isHandled(Method method) {
            return Modifier.isAbstract(method.getModifiers());
        }
    }
);

MethodHandler handler = new MethodHandler() {
    @Override
    public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
        System.out.println("Handling " + thisMethod + " via the method handler");
        return null;
    }
};

Dog dog = (Dog) factory.create(new Class<?>[0], new Object[0], handler);
dog.bark();
dog.fetch();

যা এই আউটপুট উত্পাদন করে:

ওউফ!
পদ্ধতি হ্যান্ডলারের মাধ্যমে পাবলিক অ্যাবস্ট্রাক্ট অকার্যকর মক। ডগ.ফ্যাচ () হ্যান্ডেল করা

10
+1: ঠিক আমার যা প্রয়োজন! আমি আমার নমুনা কোড দিয়ে আপনার উত্তর সম্পাদনা করব।
অ্যাডাম পেইন্টার

proxyFactory.setHandler()অবচয় করা হয়। দয়া করে ব্যবহার করুন proxy.setHandler
অ্যালিকেলজিন-কিলাকা

@ অ্যাক্সটভ্যাটটি কি উপরের কোডটিতে "কুকুর" একটি বাস্তবায়ন বা একটি ইন্টারফেস?
স্ট্যাকওভারফ্লো

-7

আপনি যেমন ক্ষেত্রে কী করতে পারেন তার একটি প্রক্সি হ্যান্ডলার রয়েছে যা কলটি আপনার বিমূর্ত শ্রেণীর বিদ্যমান পদ্ধতিগুলিতে পুনর্নির্দেশ করবে।

আপনার অবশ্যই এটি কোড করতে হবে, তবে এটি বেশ সহজ। আপনার প্রক্সি তৈরি করার জন্য, আপনাকে তাকে একটি দিতে হবে InvocationHandler। তারপরে আপনাকে কেবলমাত্র invoke(..)আপনার প্রার্থনা হ্যান্ডলারের পদ্ধতিতে পদ্ধতির ধরনটি পরীক্ষা করতে হবে । তবে সাবধান হন: আপনাকে আপনার হ্যান্ডলারের সাথে সম্পর্কিত অন্তর্নিহিত বস্তুর বিরুদ্ধে পদ্ধতি প্রকারটি পরীক্ষা করতে হবে, এবং আপনার বিমূর্ত শ্রেণির ঘোষিত ধরণের বিরুদ্ধে নয়।

যদি আমি আপনার কুকুর শ্রেণীর উদাহরণ হিসাবে নিই তবে আপনার অনুরোধ হ্যান্ডলারের আহ্বান পদ্ধতিটি দেখতে দেখতে এটির সাথে বিদ্যমান (একটি বিদ্যমান সম্পর্কিত কুকুরের সাবক্লাস বলা হয় ... ভাল ... dog)

public void invoke(Object proxy, Method method, Object[] args) {
    if(!Modifier.isAbstract(method.getModifiers())) {
        method.invoke(dog, args); // with the correct exception handling
    } else {
        // what can we do with abstract methods ?
    }
}

তবে, এমন কিছু আছে যা আমাকে ভাবতে থাকে: আমি একটি dogবস্তুর বিষয়ে কথা বলেছি । তবে, যেমন কুকুর শ্রেণি বিমূর্ত, আপনি উদাহরণ তৈরি করতে পারবেন না, সুতরাং আপনার বিদ্যমান সাবক্লাস রয়েছে। তদ্ব্যতীত, প্রক্সি উত্স কোডের কঠোর পরিদর্শন হিসাবে, আপনি আবিষ্কার করতে পারেন (প্রক্সি.জভা 62:২২ এ) যে কোনও শ্রেণি অবজেক্টের জন্য একটি প্রক্সি তৈরি করা সম্ভব নয় যা ইন্টারফেসের প্রতিনিধিত্ব করে না)।

সুতরাং, বাস্তবতা বাদে আপনি যা করতে চান তা পুরোপুরি সম্ভব।


4
আমি আপনার উত্তরটি বোঝার চেষ্টা করার সময় দয়া করে আমার সাথে সহ্য করুন ... আমার বিশেষ ক্ষেত্রে আমি প্রক্সি ক্লাসটি (রানটাইমের সময় উত্পন্ন হওয়া) সাবক্লাস হতে চাই Dog(উদাহরণস্বরূপ, আমি স্পষ্টভাবে Poodleপ্রয়োগ করে এমন একটি শ্রেণি লিখছি না fetch())। অতএব, dogপদ্ধতিগুলি চালিত করার জন্য কোনও পরিবর্তনশীল নেই ... দুঃখিত আমি যদি বিভ্রান্তি বোধ করি তবে আমাকে আরও কিছুটা ভাবতে হবে।
অ্যাডাম পেইন্টার

4
@ অ্যাডাম - আপনি কিছু সময় বাইটকোড ম্যানিপুলেশন ছাড়াই রানটাইমের সময় সাবগ্লাসগুলি তৈরি করতে পারবেন না (সিজিএলিব আমার মনে হয় এরকম কিছু করে)। সংক্ষিপ্ত উত্তরটি হ'ল গতিশীল প্রক্সিগুলি ইন্টারফেস সমর্থন করে তবে বিমূর্ত শ্রেণিগুলি নয়, কারণ দুটি খুব ভিন্ন ধারণা very ডাইনামিক্যালি প্রক্সি বিমূর্ত শ্রেণীর বুদ্ধিমান উপায়ে উপায় সম্পর্কে চিন্তা করা প্রায় অসম্ভব।
আন্দ্রেজেজ ডয়েল

4
@ আন্ডারজেজ: আমি বুঝতে পারি যে আমি যা চাইছি তার জন্য বাইটকোড ম্যানিপুলেশন প্রয়োজন (আসলে, আমি ইতিমধ্যে এএসএম ব্যবহার করে আমার সমস্যার সমাধান লিখেছি)। আমি আরও বুঝতে পারি যে জাভার গতিশীল প্রক্সিগুলি কেবল ইন্টারফেসকে সমর্থন করে। সম্ভবত আমার প্রশ্নটি পুরোপুরি পরিষ্কার ছিল না - আমি জিজ্ঞাসা করছি যে অন্য কোনও শ্রেণি রয়েছে (এটি ছাড়া অন্য কিছু java.lang.reflect.Proxy) পাওয়া যায় যা আমার প্রয়োজন অনুযায়ী করে।
অ্যাডাম পেইন্টার

4
ভাল, দীর্ঘ জিনিস ছোট করতে ... না (কমপক্ষে স্ট্যান্ডার্ড জাভা ক্লাসে)। বাইটকোড ম্যানিপুলেশন ব্যবহার করে আকাশের সীমা!
রিদুইডেল

9
আমি হ্রাস পেয়েছি কারণ এটি সত্যই প্রশ্নের উত্তর নয়। ওপি জানিয়েছে যে সে একটি ইন্টারফেস নয়, একটি ক্লাসের প্রক্সি করতে চায় এবং সচেতন যে জাভা.লাং.রেফ্লেক.প্রক্সির মাধ্যমে এটি সম্ভব নয়। আপনি কেবল সেই সত্যটির পুনরাবৃত্তি এবং অন্য কোনও সমাধান অফার করেন না।
jcsahnwaldt মনিকা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.