স্প্রিং এওপি (Spring AOP) ব্যাচ প্রসেসিং এবং ক্রস-কাটিং কনসার্ন (যেমন লগিং, সিকিউরিটি, ট্রানজেকশন ম্যানেজমেন্ট) ম্যানেজ করার জন্য একটি শক্তিশালী পদ্ধতি। স্প্রিং এওপি প্রক্সি প্যাটার্ন ব্যবহার করে Join Points এবং Advice পরিচালনা করে, যা মেথড কলের সময় নির্দিষ্ট অ্যাকশন কার্যকর করে। স্প্রিং এওপি প্রক্সি তৈরির জন্য দুটি প্রধান প্রকারের প্রক্সি ব্যবহার করে: JDK Dynamic Proxy এবং CGLIB Proxy।
প্রক্সি ক্লাস বা অবজেক্ট হল একটি অস্থায়ী ক্লাস যা মূল ক্লাসের মতোই আচরণ করে, তবে এতে কিছু অতিরিক্ত আচরণ (এডভাইস) যুক্ত করা হয়। স্প্রিংে, JDK Dynamic Proxy এবং CGLIB Proxy এই দুটি প্রক্সি মেকানিজম ব্যবহৃত হয়।
এখানে আমরা JDK Dynamic Proxy এবং CGLIB Proxy এর ভূমিকা এবং পার্থক্য সম্পর্কে বিস্তারিত আলোচনা করব।
JDK Dynamic Proxy
JDK Dynamic Proxy হল একটি প্রকারের প্রক্সি যা শুধুমাত্র ইন্টারফেস এর জন্য কাজ করে। যখন আপনি একটি JDK Dynamic Proxy ব্যবহার করেন, তখন স্প্রিং কনটেইনার একটি ডাইনামিক প্রক্সি ক্লাস তৈরি করে যা মূল ক্লাসের ইন্টারফেস ইমপ্লিমেন্ট করে এবং সেটির আচরণ বজায় রেখে অ্যাডভাইস প্রয়োগ করে।
JDK Dynamic Proxy এর কাজের প্রক্রিয়া:
- ইন্টারফেস থাকা উচিত:
JDK Dynamic Proxyশুধুমাত্র ইন্টারফেসের মাধ্যমে কাজ করে, এর মানে হচ্ছে যে এটি এমন ক্লাসের জন্য ব্যবহৃত হয় যা একটি ইন্টারফেস ইমপ্লিমেন্ট করে। - Proxy Creation: যখন
@Aspectবা প্রক্সি অ্যাডভাইস তৈরি হয়, তখন স্প্রিং জিডিকে ডাইনামিক প্রক্সি তৈরি করে। - Method Invocation: যেকোনো মেথড কলের সময়, প্রক্সি ক্লাস অ্যাডভাইস বা মেথডের আগে বা পরে কোনো নির্দিষ্ট আচরণ কার্যকর করে।
উদাহরণ: JDK Dynamic Proxy
import org.springframework.stereotype.Component;
public interface EmployeeService {
void addEmployee();
}
@Component
public class EmployeeServiceImpl implements EmployeeService {
@Override
public void addEmployee() {
System.out.println("Employee added");
}
}
Aspect Class:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.EmployeeService.addEmployee())")
public void logBefore() {
System.out.println("Method addEmployee() is about to be executed");
}
}
Spring Configuration:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
@Bean
public EmployeeService employeeService() {
return new EmployeeServiceImpl();
}
}
এখানে, JDK Dynamic Proxy ব্যবহৃত হয়েছে কারণ EmployeeService একটি ইন্টারফেস এবং আমরা এটি প্রক্সি করেছি।
CGLIB Proxy
CGLIB (Code Generation Library) হল একটি তৃতীয় পক্ষের লাইব্রেরি যা স্প্রিং এর প্রক্সি তৈরি করতে ব্যবহৃত হয়। CGLIB Proxy মূলত কোনো ক্লাসের সাবক্লাস তৈরি করে এবং এতে অ্যাডভাইস যুক্ত করে। এটি ইন্টারফেস ছাড়াও যেকোনো ক্লাসের জন্য প্রক্সি তৈরি করতে সক্ষম। CGLIB ব্যবহার করার জন্য কোনো ইন্টারফেস থাকতে হবে না, এটি সরাসরি ক্লাসের উপরে কাজ করে।
CGLIB Proxy এর কাজের প্রক্রিয়া:
- Subclass Creation: CGLIB একটি নতুন ক্লাস তৈরি করে যা মূল ক্লাসের একটি সাবক্লাস।
- Method Interception: এই সাবক্লাসে মেথডগুলিকে ইন্টারসেপ্ট করা হয় এবং সেখানে অ্যাডভাইস অ্যাড করা হয়।
- Direct Class Proxying: CGLIB ক্লাসের জন্য ব্যবহৃত হয় যেগুলোর কোনো ইন্টারফেস নেই।
উদাহরণ: CGLIB Proxy
import org.springframework.stereotype.Component;
public class EmployeeService {
public void addEmployee() {
System.out.println("Employee added");
}
}
Aspect Class:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.EmployeeService.addEmployee())")
public void logBefore() {
System.out.println("Method addEmployee() is about to be executed");
}
}
Spring Configuration:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true) // Use CGLIB proxy
public class AppConfig {
@Bean
public EmployeeService employeeService() {
return new EmployeeService();
}
}
এখানে, @EnableAspectJAutoProxy(proxyTargetClass = true) দ্বারা স্প্রিংকে CGLIB প্রক্সি ব্যবহার করার নির্দেশ দেওয়া হয়েছে।
JDK Dynamic Proxy এবং CGLIB Proxy এর মধ্যে পার্থক্য
| বৈশিষ্ট্য | JDK Dynamic Proxy | CGLIB Proxy |
|---|---|---|
| প্রক্সি ধরনের | ইন্টারফেস ভিত্তিক প্রক্সি | ক্লাস ভিত্তিক প্রক্সি |
| সীমাবদ্ধতা | শুধুমাত্র ইন্টারফেস ইমপ্লিমেন্ট করা ক্লাসে কাজ করে | কোনো ইন্টারফেস ছাড়া সরাসরি ক্লাসের জন্য কাজ করে |
| সাবক্লাস তৈরি | কোনো সাবক্লাস তৈরি করে না | একটি সাবক্লাস তৈরি করে |
| প্রকল্পের কার্যকারিতা | ইনহেরিটেড মেথডের জন্য কাজ করে না | ইনহেরিটেড মেথডের জন্য কাজ করতে পারে |
| পারফরম্যান্স | CGLIB এর তুলনায় কিছুটা কম পারফরম্যান্স | বেশি পারফরম্যান্স |
কোন পরিস্থিতিতে কোন প্রক্সি ব্যবহার করবেন?
- JDK Dynamic Proxy: যদি আপনার ক্লাস ইন্টারফেস ইমপ্লিমেন্ট করে, তবে JDK Dynamic Proxy ব্যবহার করা উচিত। এটি বেশি নমনীয় এবং ইন্টারফেস ভিত্তিক। সাধারণত, এটি সার্ভিস বা ডিএও ক্লাসের জন্য ব্যবহৃত হয়।
- CGLIB Proxy: যদি আপনার ক্লাস কোনো ইন্টারফেস ইমপ্লিমেন্ট না করে, তবে CGLIB Proxy ব্যবহার করতে হবে। CGLIB সরাসরি ক্লাসের সাবক্লাস তৈরি করে, তাই আপনি ক্লাসের মেথডে প্রক্সি অ্যাড করতে পারেন।
সারাংশ
স্প্রিং এওপি (Spring AOP) তে JDK Dynamic Proxy এবং CGLIB Proxy দুটি গুরুত্বপূর্ণ প্রক্সি মেকানিজম, যা নির্দিষ্ট পয়েন্টকাট এবং অ্যাডভাইস প্রয়োগের জন্য ব্যবহৃত হয়। JDK Dynamic Proxy ইন্টারফেস ভিত্তিক প্রক্সি তৈরি করে, এবং CGLIB Proxy সরাসরি ক্লাসের সাবক্লাস তৈরি করে। এই দুটি প্রক্সি ব্যবহারের সিদ্ধান্ত মূলত আপনার ক্লাসের আর্কিটেকচার এবং প্রয়োজনে নির্ভর করে।