Java Reflection API-তে Dynamic Proxy একটি শক্তিশালী ফিচার যা আপনাকে একটি ইন্টারফেসের জন্য রানটাইমে প্রক্সি ক্লাস তৈরি করতে সাহায্য করে। এই প্রক্রিয়ায়, আপনি কোনও ইন্টারফেসের জন্য একটি ডাইনামিক প্রক্সি তৈরি করতে পারেন, যা একটি নির্দিষ্ট InvocationHandler ব্যবহার করে কাজ করে। InvocationHandler ইন্টারফেসটি ইমপ্লিমেন্ট করে আপনি সেই প্রক্সির মেথডগুলির আচরণ কাস্টমাইজ করতে পারেন।
Dynamic Proxy এবং InvocationHandler এর ব্যবহার:
- Dynamic Proxy:
- Dynamic Proxy আপনাকে রানটাইমে একটি নতুন ক্লাস তৈরি করতে দেয় যা একটি নির্দিষ্ট ইন্টারফেস ইমপ্লিমেন্ট করে। এটি সেই ইন্টারফেসের সমস্ত মেথডের জন্য
InvocationHandlerনির্ধারণ করে, যা মেথড কল হওয়ার সময় কাস্টম আচরণ নির্ধারণ করে।
- Dynamic Proxy আপনাকে রানটাইমে একটি নতুন ক্লাস তৈরি করতে দেয় যা একটি নির্দিষ্ট ইন্টারফেস ইমপ্লিমেন্ট করে। এটি সেই ইন্টারফেসের সমস্ত মেথডের জন্য
- InvocationHandler:
InvocationHandlerএকটি ইন্টারফেস, যার একটি মেথড রয়েছে:invoke(), যা আপনাকে প্রক্সি ক্লাসের মেথড কল করার সময় কাস্টম কোড লেখার সুযোগ দেয়।
InvocationHandler ইন্টারফেসের মেথড:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
proxy: এটি প্রক্সি অবজেক্ট।method: এটি মেথড অবজেক্ট যা কল করা হয়েছে।args: এটি মেথডের প্যারামিটারগুলোর মানের অ্যারে।
Dynamic Proxy তৈরি করার উদাহরণ:
ধরা যাক, আমাদের একটি Hello ইন্টারফেস আছে এবং আমরা একটি প্রক্সি ক্লাস তৈরি করতে চাই যা Hello ইন্টারফেস ইমপ্লিমেন্ট করবে। আমরা InvocationHandler ব্যবহার করে কাস্টম আচরণ নির্ধারণ করব।
Step 1: Hello ইন্টারফেস তৈরি করা
public interface Hello {
void sayHello(String name);
}
Step 2: InvocationHandler ইমপ্লিমেন্টেশন
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class HelloInvocationHandler implements InvocationHandler {
private final Object target;
public HelloInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method call: " + method.getName());
// যদি প্রক্সি অবজেক্টে কোন মেথড কল করা হয়, তবে টার্গেট অবজেক্টে সেই মেথড কল হবে
Object result = method.invoke(target, args);
System.out.println("After method call: " + method.getName());
return result;
}
}
Step 3: Hello ইন্টারফেসের একটি কনক্রিট ক্লাস তৈরি করা
public class HelloImpl implements Hello {
@Override
public void sayHello(String name) {
System.out.println("Hello, " + name + "!");
}
}
Step 4: Dynamic Proxy তৈরি করা এবং ব্যবহার করা
import java.lang.reflect.Proxy;
public class DynamicProxyExample {
public static void main(String[] args) {
// HelloImpl ক্লাসের অবজেক্ট তৈরি
Hello realHello = new HelloImpl();
// InvocationHandler তৈরি করা
InvocationHandler handler = new HelloInvocationHandler(realHello);
// Dynamic Proxy তৈরি করা
Hello proxyHello = (Hello) Proxy.newProxyInstance(
Hello.class.getClassLoader(),
new Class<?>[] { Hello.class },
handler
);
// প্রক্সি অবজেক্টের মাধ্যমে মেথড কল করা
proxyHello.sayHello("John");
}
}
কোড বিশ্লেষণ:
Helloইন্টারফেস:- এখানে একটি সাধারণ
Helloইন্টারফেস তৈরি করা হয়েছে, যার একটি মেথডsayHelloরয়েছে।
- এখানে একটি সাধারণ
HelloInvocationHandlerক্লাস:InvocationHandlerইমপ্লিমেন্ট করে, এখানেinvoke()মেথডে আমরা প্রক্সি মেথড কলের আগে এবং পরে কিছু কাস্টম লজিক যোগ করেছি।method.invoke(target, args)কলটি মূলHelloImplক্লাসের মেথডটিকে কল করবে।
HelloImplক্লাস:- এটি
Helloইন্টারফেসের একটি কনক্রিট ক্লাস, যাsayHelloমেথডের বাস্তবায়ন প্রদান করে।
- এটি
DynamicProxyExampleক্লাস:- এখানে
Proxy.newProxyInstance()মেথড ব্যবহার করেHelloইন্টারফেসের একটি ডাইনামিক প্রক্সি তৈরি করা হয়েছে। newProxyInstance()মেথডে আমরা:Hello.class.getClassLoader(): ক্লাসলোডার প্রদান করি।new Class<?>[] { Hello.class }: ইন্টারফেসের অ্যারে প্রদান করি।handler:InvocationHandlerপ্রদান করি।
- এখানে
- প্রক্সি অবজেক্টে মেথড কল:
proxyHello.sayHello("John");কল করার পর, এটি প্রথমেHelloInvocationHandlerএরinvoke()মেথডে চলে যাবে এবং তারপর মূলsayHelloমেথডটি কল হবে।
আউটপুট:
Before method call: sayHello
Hello, John!
After method call: sayHello
Dynamic Proxy এর সুবিধা:
- ডাইনামিক মেথড রাউটিং: আপনি প্রক্সি অবজেক্টের মাধ্যমে একটি নির্দিষ্ট মেথডের কাস্টম আচরণ বা লজিক যুক্ত করতে পারেন।
- কমপ্লেক্স ফ্রেমওয়ার্ক: এই প্রক্রিয়াটি অনেক Java ফ্রেমওয়ার্ক (যেমন Spring, Hibernate) এ ব্যবহৃত হয় যেখানে ডাইনামিক প্রক্সি ব্যবহার করে মেথড কল হ্যান্ডল করা হয়।
- মডুলার কোড: বিভিন্ন মেথড কলের জন্য আলাদা কাস্টম আচরণ তৈরি করা সম্ভব, যা কোডকে আরও মডুলার এবং রিইউজেবল করে তোলে।
Java Reflection API এর Dynamic Proxy এবং InvocationHandler ক্লাস Java প্রোগ্রামিংয়ে অত্যন্ত শক্তিশালী টুল। এগুলি আপনাকে runtime-এ ইন্টারফেসের জন্য প্রক্সি তৈরি করতে এবং সেই প্রক্সির মেথডগুলির আচরণ কাস্টমাইজ করতে সাহায্য করে। এটি অনেক ফ্রেমওয়ার্ক এবং লাইব্রেরির ভিতরে ব্যবহৃত একটি গুরুত্বপূর্ণ প্রযুক্তি, যা ডাইনামিক কোডিং এবং ফ্লেক্সিবল সিস্টেম ডিজাইন করতে সক্ষম।
Read more