Spring AOP (Aspect-Oriented Programming) এর মাধ্যমে, Proxy ব্যবহার করে একটি Aspect (যেমন লোগিং, সিকিউরিটি, ট্রান্সঅ্যাকশন ম্যানেজমেন্ট) বিভিন্ন পয়েন্টে প্রয়োগ করা হয়। Spring AOP প্রাথমিকভাবে JDK Dynamic Proxy অথবা CGLIB Proxy ব্যবহার করে একটি target অবজেক্টের চারপাশে একটি প্রোক্সি তৈরি করে, যা সেই অবজেক্টের ওপর বিভিন্ন ক্রস-কাটিং কনসার্ন কার্যকর করে।
Spring AOP তে Proxy ব্যবহার করার মাধ্যমে আমরা একটি অবজেক্টের কার্যকারিতাকে বর্ধিত করতে পারি, যেমন, কোন মেথড রান হওয়ার আগে বা পরে অতিরিক্ত কোড চালানো।
এখানে Proxy ব্যবহারের উদাহরণ দেখানো হবে, যেখানে JDK Dynamic Proxy এবং CGLIB Proxy এর মাধ্যমে AOP ব্যবহার করা হবে।
1. Proxy কি?
Proxy হল একটি অবজেক্ট যা আসল অবজেক্টের প্রতিনিধিত্ব করে এবং তার কার্যকারিতা অনুকরণ করে। Spring AOP এ Proxy তৈরি করা হয় যাতে অ্যাপ্লিকেশনের মেথড কলের আগের বা পরের কার্যক্রম নির্ধারণ করা যায়।
Spring AOP সাধারণত দুটি ধরণের Proxy ব্যবহার করে:
- JDK Dynamic Proxy: যদি টার্গেট অবজেক্টটি একটি ইন্টারফেস ইমপ্লিমেন্ট করে, তবে Spring একটি JDK ডায়নামিক প্রোক্সি তৈরি করে।
- CGLIB Proxy: যদি টার্গেট অবজেক্টটি কোনো ইন্টারফেস ইমপ্লিমেন্ট না করে, তবে CGLIB (Code Generation Library) ব্যবহার করে Spring একটি সাব-ক্লাস প্রোক্সি তৈরি করে।
2. Spring AOP এ Proxy ব্যবহারের উদাহরণ
এই উদাহরণে আমরা দেখব কিভাবে Spring AOP Proxy ব্যবহার করে একটি LoggingAspect অ্যাপ্লাই করা যায়, যা JDK Dynamic Proxy এর মাধ্যমে কাজ করবে। উদাহরণস্বরূপ, আমরা একটি UserService ক্লাস তৈরি করব এবং তার ওপর LoggingAspect প্রোক্সি প্রয়োগ করব।
2.1 প্রজেক্ট ডিপেনডেন্সি
প্রথমে আপনার pom.xml ফাইলে নিচের ডিপেনডেন্সি যোগ করতে হবে:
<dependencies>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Starter AOP -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
2.2 Service ক্লাস (Target Class)
এখন একটি Service ক্লাস তৈরি করা হবে, যেটি createUser() এবং deleteUser() মেথড থাকবে।
package com.example.demo.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void createUser(String userName) {
System.out.println("User " + userName + " created successfully.");
}
public void deleteUser(String userName) {
System.out.println("User " + userName + " deleted successfully.");
}
}
এখানে, UserService ক্লাস দুটি মেথড রাখে যা ইউজার তৈরি এবং মুছে ফেলার কাজ করে।
2.3 Aspect (Proxy) তৈরি করা
Spring AOP Proxy ব্যবহার করে Before এবং After Advice কার্যকর করা যাবে। LoggingAspect ক্লাসে আমরা @Before এবং @After অ্যানোটেশন দিয়ে কার্যক্রম শুরু এবং শেষের লগিং কার্যকর করব।
package com.example.demo.aspect;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.After;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
// @Before annotation indicates that this method will run before the target method is executed
@Before("execution(* com.example.demo.service.UserService.*(..))")
public void beforeMethodExecution() {
System.out.println("Before method execution - LoggingAspect");
}
// @After annotation indicates that this method will run after the target method is executed
@After("execution(* com.example.demo.service.UserService.*(..))")
public void afterMethodExecution() {
System.out.println("After method execution - LoggingAspect");
}
}
এখানে:
- @Before: এই অ্যানোটেশনটি নিশ্চিত করে যে মেথডটি টার্গেট মেথডের আগে কার্যকর হবে।
- @After: এই অ্যানোটেশনটি টার্গেট মেথডের পর কার্যকর হবে।
execution(* com.example.demo.service.UserService.*(..)): Spring AOP এক্সপ্রেশন যাUserServiceক্লাসের সমস্ত মেথডে AOP অ্যাপ্লাই করবে।
2.4 Application ক্লাস (Main Class)
Spring Boot অ্যাপ্লিকেশনে UserService মেথড কল করার জন্য CommandLineRunner ইন্টারফেস ব্যবহার করা হবে।
package com.example.demo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
@Autowired
private UserService userService;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
userService.createUser("John");
userService.deleteUser("John");
}
}
এখানে, CommandLineRunner ব্যবহার করে আমরা UserService এর মেথডগুলো কল করেছি।
2.5 Proxy এর মাধ্যমে Advice কার্যকর করা
Spring AOP দ্বারা একটি Proxy তৈরি করা হবে, যেখানে LoggingAspect এর beforeMethodExecution() এবং afterMethodExecution() মেথডগুলি UserService এর মেথডের আগে এবং পরে কার্যকর হবে।
2.6 আউটপুট
Before method execution - LoggingAspect
User John created successfully.
After method execution - LoggingAspect
Before method execution - LoggingAspect
User John deleted successfully.
After method execution - LoggingAspect
এখানে, Before Advice মেথড কল হওয়ার আগে এবং After Advice মেথড কল হওয়ার পরে কার্যকর হবে।
3. JDK Dynamic Proxy এবং CGLIB Proxy
Spring AOP দ্বারা দুইটি ধরনের প্রোক্সি তৈরি করা যায়:
- JDK Dynamic Proxy: যদি টার্গেট ক্লাস একটি ইন্টারফেস ইমপ্লিমেন্ট করে, তাহলে Spring JDK Dynamic Proxy ব্যবহার করবে।
- CGLIB Proxy: যদি টার্গেট ক্লাস কোনো ইন্টারফেস ইমপ্লিমেন্ট না করে, তাহলে Spring CGLIB Proxy ব্যবহার করবে।
3.1 JDK Dynamic Proxy
যদি UserService ক্লাস একটি ইন্টারফেস UserServiceInterface ইমপ্লিমেন্ট করে, তবে Spring AOP JDK Dynamic Proxy তৈরি করবে।
UserServiceInterface
package com.example.demo.service;
public interface UserServiceInterface {
void createUser(String userName);
void deleteUser(String userName);
}
UserService ইমপ্লিমেন্টেশন
package com.example.demo.service;
import org.springframework.stereotype.Service;
@Service
public class UserService implements UserServiceInterface {
@Override
public void createUser(String userName) {
System.out.println("User " + userName + " created successfully.");
}
@Override
public void deleteUser(String userName) {
System.out.println("User " + userName + " deleted successfully.");
}
}
এখানে, UserService এখন UserServiceInterface ইমপ্লিমেন্ট করছে এবং Spring JDK Dynamic Proxy ব্যবহার করবে।
3.2 CGLIB Proxy
যদি UserService ক্লাস কোনো ইন্টারফেস ইমপ্লিমেন্ট না করে, তবে Spring CGLIB Proxy ব্যবহার করবে, যা সরাসরি ক্লাসের সাবক্লাস তৈরি করে।
সারাংশ
Spring AOP এ Proxy ব্যবহারের মাধ্যমে আপনি একটি টার্গেট ক্লাসের উপর ক্রস-কাটিং কনসার্ন কার্যকর করতে পারেন। Before এবং After Advice এর মাধ্যমে মেথডের আগে বা পরে অতিরিক্ত কাজ করা সম্ভব হয়। Spring AOP JDK Dynamic Proxy এবং CGLIB Proxy ব্যবহার করে প্রোক্সি তৈরি করে, যার মাধ্যমে AOP কার্যক্রম একটি টার্গেট মেথডে প্রয়োগ করা যায়। Spring AOP এর মাধ্যমে কোডের পুনঃব্যবহারযোগ্যতা এবং কার্যকারিতা বৃদ্ধি পায়।
Read more