স্প্রিং ডিপেনডেন্সি ইনজেকশন (Spring Dependency Injection, DI) হল স্প্রিং ফ্রেমওয়ার্কের একটি প্রধান বৈশিষ্ট্য যা সফটওয়্যার ডিজাইনে loosely coupled (ঢিলা যুক্ত) আর্কিটেকচার তৈরি করতে সাহায্য করে। DI এর মাধ্যমে একটি ক্লাস তার প্রয়োজনীয় ডিপেনডেন্সি গুলি (অন্য ক্লাসের অবজেক্ট) বাইরের মাধ্যমে পায়, অর্থাৎ একে নিজে তৈরি করতে হয় না, বরং স্প্রিং কনটেইনার সেটি ইনজেক্ট করে।
স্প্রিং এর ডিপেনডেন্সি ইনজেকশন সফটওয়্যার ডিজাইনে ভালো টেস্টেবিলিটি, ম্যানটেইনেবল কোড এবং ফ্লেক্সিবিলিটি নিয়ে আসে। এই প্রযুক্তি কনটেইনার-ভিত্তিক এবং IoC (Inversion of Control) প্রিন্সিপলের উপর ভিত্তি করে কাজ করে।
Spring DI এর বেসিক কনসেপ্ট
1. Dependency Injection (DI) Definition
ডিপেনডেন্সি ইনজেকশন হল এমন একটি ডিজাইন প্যাটার্ন, যেখানে কোনো ক্লাস তার ডিপেনডেন্সি গুলি নিজে তৈরির পরিবর্তে বাইরের কোনো সিস্টেম থেকে (যেমন স্প্রিং কনটেইনার থেকে) গ্রহণ করে। এর ফলে কোডের cohesion বৃদ্ধি পায় এবং coupling হ্রাস পায়।
উদাহরণ:
public class EmployeeService {
private EmployeeRepository employeeRepository; // Dependency
// Constructor-based DI
public EmployeeService(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}
public void saveEmployee(Employee employee) {
employeeRepository.save(employee);
}
}
এখানে, EmployeeService ক্লাস EmployeeRepository এর উপর নির্ভরশীল। তবে, EmployeeRepository ইনজেক্ট করার দায়িত্ব স্প্রিং কনটেইনারের।
2. Types of Dependency Injection
স্প্রিং ফ্রেমওয়ার্কে DI প্রধানত তিনটি ধরণের হয়:
- Constructor-based DI
- Setter-based DI
- Field-based DI
Constructor-based DI
এই ধরনের ইনজেকশনে, ক্লাসের কনস্ট্রাক্টরের মাধ্যমে ডিপেনডেন্সি ইনজেক্ট করা হয়।
@Component
public class EmployeeService {
private final EmployeeRepository employeeRepository;
@Autowired // Constructor-based DI
public EmployeeService(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}
public void saveEmployee(Employee employee) {
employeeRepository.save(employee);
}
}
এখানে, EmployeeRepository ইনজেক্ট করা হচ্ছে কনস্ট্রাক্টরের মাধ্যমে।
Setter-based DI
এই ধরনের ইনজেকশনে, ডিপেনডেন্সি সেটার মেথডের মাধ্যমে ইনজেক্ট করা হয়।
@Component
public class EmployeeService {
private EmployeeRepository employeeRepository;
@Autowired // Setter-based DI
public void setEmployeeRepository(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}
public void saveEmployee(Employee employee) {
employeeRepository.save(employee);
}
}
এখানে, ডিপেনডেন্সি ইনজেক্ট করা হচ্ছে setEmployeeRepository মেথডের মাধ্যমে।
Field-based DI
এই ধরনের ইনজেকশনে, ডিপেনডেন্সি সরাসরি ক্লাসের ফিল্ডে ইনজেক্ট করা হয়।
@Component
public class EmployeeService {
@Autowired // Field-based DI
private EmployeeRepository employeeRepository;
public void saveEmployee(Employee employee) {
employeeRepository.save(employee);
}
}
এখানে, স্প্রিং কনটেইনার সরাসরি employeeRepository ফিল্ডে ইনজেক্ট করে।
3. Inversion of Control (IoC)
Inversion of Control (IoC) একটি ডিজাইন প্যাটার্ন যেখানে একটি ক্লাস তার ডিপেনডেন্সি নিজের থেকে তৈরি করে না, বরং তা অন্য একটি সিস্টেম (যেমন স্প্রিং কনটেইনার) দ্বারা সরবরাহ করা হয়। DI হল IoC এর একটি প্রকার। এর ফলে, স্প্রিং কনটেইনার অ্যাপ্লিকেশনের অবজেক্ট ম্যানেজ করে এবং ডিপেনডেন্সি ইনজেক্ট করে।
4. Bean Configuration and Spring Container
স্প্রিং কনটেইনার অ্যাপ্লিকেশনের বিইনগুলো (object) ম্যানেজ করে। স্প্রিং কনটেইনারে দুই ধরনের বিইন কনফিগারেশন হতে পারে:
- XML-based Configuration: প্রাচীন স্প্রিং কনফিগারেশন পদ্ধতি।
- Annotation-based Configuration: আধুনিক এবং সহজ পদ্ধতি যেখানে অ্যানোটেশন ব্যবহার করে বিইন কনফিগার করা হয়।
XML-based Configuration (Traditional Way)
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="employeeRepository" class="com.example.EmployeeRepository"/>
<bean id="employeeService" class="com.example.EmployeeService">
<constructor-arg ref="employeeRepository"/>
</bean>
</beans>
Annotation-based Configuration (Modern Way)
@Component
public class EmployeeRepository {
// Repository implementation
}
@Component
public class EmployeeService {
private final EmployeeRepository employeeRepository;
@Autowired
public EmployeeService(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}
public void saveEmployee(Employee employee) {
employeeRepository.save(employee);
}
}
এখানে, @Component অ্যানোটেশন ক্লাসগুলোর উপর স্প্রিং কনটেইনারের দৃষ্টি আকর্ষণ করবে এবং @Autowired অ্যানোটেশন ডিপেনডেন্সি ইনজেকশন করবে।
5. Advantages of Dependency Injection
ডিপেনডেন্সি ইনজেকশন ব্যবহার করার অনেক সুবিধা রয়েছে:
- Loose Coupling: এটি কোডকে ঢিলা যুক্ত করে, কারণ ডিপেনডেন্সি সরাসরি তৈরি করার প্রয়োজন পড়ে না।
- Testability: স্প্রিং DI ব্যবহার করে সহজে মক বা স্টাব অবজেক্ট ইনজেক্ট করা যায়, যা ইউনিট টেস্টিংকে সহজ করে।
- Flexibility: ডিপেনডেন্সি গুলি পরিবর্তন করা সহজ, কারণ আপনি সরাসরি ক্লাসে পরিবর্তন না করে কনফিগারেশন ফাইলে পরিবর্তন করতে পারেন।
- Maintainability: কোড মেইনটেইন করা সহজ, কারণ বিভিন্ন অবজেক্টের তৈরি এবং ব্যবহার আলাদা রাখা হয়।
6. Scope of Beans in Spring DI
স্প্রিং ডিপেনডেন্সি ইনজেকশনে Bean Scope নির্ধারণ করা হয়, যা ব্যাখ্যা করে কোন নির্দিষ্ট অবজেক্ট কিভাবে এবং কখন তৈরি হবে। প্রধান bean scopes হল:
- Singleton (ডিফল্ট): একটি কনটেইনারের মধ্যে একটি মাত্র ইনস্ট্যান্স তৈরি হবে।
- Prototype: প্রতিবার নতুন একটি অবজেক্ট তৈরি হবে।
- Request: ওয়েব অ্যাপ্লিকেশনের একটি HTTP রিকোয়েস্টের জন্য একটি নতুন ইনস্ট্যান্স তৈরি হবে।
- Session: ব্যবহারকারীর সেশন অনুযায়ী একটি ইনস্ট্যান্স তৈরি হবে।
সারাংশ
Spring Dependency Injection (DI) হল একটি শক্তিশালী ডিজাইন প্যাটার্ন যা অ্যাপ্লিকেশন কোডে ঢিলামি (loose coupling) এনে দেয়। স্প্রিং DI প্রিন্সিপল কোডের মেইনটেইনেবলিটি এবং টেস্টেবিলিটি উন্নত করতে সাহায্য করে। এটি স্প্রিং কনটেইনারের মাধ্যমে অবজেক্টের ডিপেনডেন্সি ইনজেক্ট করে, যার ফলে ডিপেনডেন্সি ম্যানেজমেন্ট খুবই সহজ এবং কার্যকর হয়। DI এর মাধ্যমে, স্প্রিং ফ্রেমওয়ার্ক ডিপেনডেন্সি ইনজেকশন ব্যবস্থাপনাকে সহজ, রিইউজেবল এবং ক্লিন কোডের জন্য আরও উপযুক্ত করে তোলে।
Spring Dependency Injection (DI) হল Spring Framework-এর একটি গুরুত্বপূর্ণ ফিচার যা ইনস্ট্যান্সের মধ্যে প্রয়োজনীয় অবজেক্টগুলো স্বয়ংক্রিয়ভাবে ইনজেক্ট করে। এটি একটি ডিজাইন প্যাটার্ন, যেখানে অবজেক্টের নির্ভরতা (dependencies) বাইরের কোনও সিস্টেম (যেমন Spring Container) দ্বারা সরবরাহ করা হয়, পরিবর্তে নিজে সেগুলি তৈরি করে না। Spring DI এর মাধ্যমে কোডের মডুলারিটি বৃদ্ধি পায়, টেস্টিং সহজ হয় এবং কোডের রক্ষণাবেক্ষণ এবং পুনঃব্যবহারযোগ্যতা উন্নত হয়।
Spring DI এর কাজের প্রক্রিয়া খুবই সরল, যেখানে Spring Container একটি অবজেক্ট তৈরি করে এবং সেই অবজেক্টের জন্য প্রয়োজনীয় অন্যান্য অবজেক্টগুলোর ইনজেকশন করে।
Spring DI এর কাজের প্রক্রিয়া
Spring DI এর কাজের প্রক্রিয়া কিছু নির্দিষ্ট ধাপে বিভক্ত করা যায়। সেগুলো হলো:
১. Bean Configuration (বিন কনফিগারেশন)
Spring DI এর প্রথম ধাপ হল Bean Configuration। এখানে Spring Container-এ কোন কোন অবজেক্ট (Beans) তৈরি হবে, তাদের কনফিগারেশন বা সংজ্ঞা দেওয়া হয়। Beans তৈরি করার জন্য সাধারণত XML Configuration, Java Configuration (annotated classes), অথবা Annotation-based Configuration ব্যবহৃত হয়।
XML Configuration Example:
<bean id="car" class="com.example.Car"/>
<bean id="engine" class="com.example.Engine"/>
Java Configuration Example:
@Configuration
@ComponentScan("com.example")
public class AppConfig {
}
২. Creating Beans in the Container
Spring Container কনফিগারেশন ফাইল থেকে নির্দিষ্ট Beans তৈরি করে। Spring Container সব Beans কে singleton বা prototype scope অনুযায়ী ইন্সট্যান্সিয়েট (instantiate) করে।
Example of Bean Definition in Java:
@Component
public class Car {
private Engine engine;
@Autowired
public Car(Engine engine) {
this.engine = engine;
}
}
Bean Creation in Container:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Car car = context.getBean(Car.class);
৩. Dependency Injection (ডিপেনডেন্সি ইনজেকশন)
Spring DI এর মূল কাজ হল অবজেক্টের নির্ভরতা ইনজেক্ট করা। Spring Container যখন একটি Bean তৈরি করে, তখন সেই Bean এর জন্য নির্দিষ্ট সব ইনজেকশন ডিপেনডেন্সি অটোমেটিক্যালি ইনজেক্ট করে। এই ইনজেকশনটি Constructor Injection, Setter Injection, অথবা Field Injection মাধ্যমে হতে পারে।
Constructor Injection:
@Component
public class Car {
private Engine engine;
@Autowired
public Car(Engine engine) {
this.engine = engine;
}
}
এখানে, Engine অবজেক্টটি Car অবজেক্টের কনস্ট্রাক্টর ইনজেকশন মাধ্যমে প্রদান করা হচ্ছে।
Setter Injection:
@Component
public class Car {
private Engine engine;
@Autowired
public void setEngine(Engine engine) {
this.engine = engine;
}
}
Setter Injection এর মাধ্যমে Car এর setEngine() মেথডের মাধ্যমে Engine ইনজেক্ট করা হচ্ছে।
Field Injection:
@Component
public class Car {
@Autowired
private Engine engine;
}
Field Injection-এ @Autowired অ্যানোটেশন সরাসরি ফিল্ডে দেওয়া হয়, এবং Spring Container স্বয়ংক্রিয়ভাবে ইনজেকশন সম্পন্ন করে।
৪. Resolving Dependencies (ডিপেনডেন্সি রিজল্ভ করা)
Spring Container অটোমেটিক্যালি যেকোনো Bean এর ডিপেনডেন্সি রিজল্ভ করে এবং সেগুলিকে ইনজেক্ট করে। যেমন, যদি Car Bean-এ Engine Bean এর প্রয়োজন থাকে, তাহলে Spring Container স্বয়ংক্রিয়ভাবে Engine Bean কে Car Bean-এ ইনজেক্ট করবে।
@Component
public class Engine {
private String model;
public Engine() {
this.model = "V8";
}
public String getModel() {
return model;
}
}
Car Bean এর মধ্যে Engine Bean ইনজেক্ট হওয়া:
@Configuration
@ComponentScan("com.example")
public class AppConfig {
}
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Car car = context.getBean(Car.class);
System.out.println(car.getEngine().getModel());
}
}
এখানে Engine Bean কে Car Bean এর মধ্যে স্বয়ংক্রিয়ভাবে ইনজেক্ট করা হবে, এবং ফলস্বরূপ আউটপুট হবে "V8"।
৫. Lifecycle Management (লাইফসাইকেল ম্যানেজমেন্ট)
Spring Container Bean এর লাইফসাইকেল পরিচালনা করে। এর মধ্যে Bean এর initialization (ইনিশিয়ালাইজেশন) এবং destruction (ডেস্ট্রাকশন) রয়েছে। Bean এর lifecycle ম্যানেজ করার জন্য @PostConstruct এবং @PreDestroy অ্যানোটেশন ব্যবহার করা যায়।
@Component
public class Car {
@PostConstruct
public void init() {
System.out.println("Car Initialized!");
}
@PreDestroy
public void destroy() {
System.out.println("Car Destroyed!");
}
}
Spring Container স্বয়ংক্রিয়ভাবে init() এবং destroy() মেথড কল করবে Bean এর জীবনচক্র অনুযায়ী।
৬. Context Management
Spring Container Bean তৈরি, Dependency Injection, এবং Bean এর লাইফসাইকেল পরিচালনা করার পর, আপনি Bean গুলি Spring Context থেকে অ্যাক্সেস করতে পারেন। Spring Context হল Spring Container যা Spring Beans এর রেজিস্ট্রি হিসেবে কাজ করে।
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Car car = context.getBean(Car.class);
System.out.println(car);
context.close();
context.getBean(Car.class) এর মাধ্যমে Car Bean অ্যাক্সেস করা হবে, এবং context.close() এর মাধ্যমে Spring Context বন্ধ করা হবে।
সারাংশ
Spring Dependency Injection (DI) একটি গুরুত্বপূর্ণ ফিচার যা Spring Framework-এ কোডের মডুলারিটি, রক্ষণাবেক্ষণ এবং টেস্টিং সহজ করে তোলে। Spring DI এর কাজের প্রক্রিয়া হলো:
- Bean Configuration: Spring Container Beans কনফিগার করে।
- Bean Creation: Spring Beans তৈরি করা হয়।
- Dependency Injection: DI এর মাধ্যমে অবজেক্টের নির্ভরতা ইনজেক্ট করা হয়।
- Resolving Dependencies: Spring Container Dependencies রিজল্ভ করে ইনজেক্ট করে।
- Lifecycle Management: Bean এর লাইফসাইকেল Spring Container পরিচালনা করে।
- Context Management: Spring Context থেকে Beans অ্যাক্সেস করা হয়।
Spring DI ব্যবহার করার মাধ্যমে কোডের পুনঃব্যবহারযোগ্যতা, ফ্লেক্সিবিলিটি এবং টেস্টিং সহজতর হয়।
স্প্রিং ফ্রেমওয়ার্কে ডিপেনডেন্সি ইনজেকশন (Dependency Injection - DI) একটি গুরুত্বপূর্ণ ডিজাইন প্যাটার্ন, যা অ্যাপ্লিকেশনে বিভিন্ন ক্লাসের মধ্যে সম্পর্ক স্থাপন করে এবং তাদের একে অপরের সাথে যোগাযোগ স্থাপন করতে সাহায্য করে। স্প্রিং DI আপনাকে অবজেক্ট তৈরি এবং ডিপেনডেন্সি ম্যানেজমেন্ট এর কাজ অ্যাপ্লিকেশন কন্টেইনারের মাধ্যমে স্বয়ংক্রিয়ভাবে করতে সাহায্য করে। এতে অ্যাপ্লিকেশনের লজিককে আরও মডুলার, সহজে পরীক্ষণযোগ্য এবং রিইউজেবল করা যায়।
স্প্রিং DI দুটি প্রধান ধরনের ইনজেকশন পদ্ধতি সমর্থন করে:
- Constructor Injection
- Setter Injection
1. Constructor Injection
Constructor Injection হল একটি পদ্ধতি যেখানে ডিপেনডেন্সি একটি কনস্ট্রাক্টরের মাধ্যমে ইনজেক্ট করা হয়। এটি ইনজেকশন পদ্ধতির মধ্যে সবচেয়ে নিরাপদ এবং সুপারিশকৃত পদ্ধতি, কারণ এটি অবজেক্টের ডিপেনডেন্সিগুলো কনস্ট্রাকশন সময় নির্ধারণ করে এবং একবার অবজেক্ট তৈরি হলে ডিপেনডেন্সিগুলি পরিবর্তন করা সম্ভব নয়। এটি ফাইন গ্রানুলার কনট্রোল এবং ইমিউটেবল অবজেক্ট সৃষ্টিতে সহায়ক।
উদাহরণ:
// Service Interface
public interface GreetingService {
void greet();
}
// Service Implementation
public class GreetingServiceImpl implements GreetingService {
@Override
public void greet() {
System.out.println("Hello, Welcome to Constructor Injection!");
}
}
// Client Class
public class Client {
private GreetingService greetingService;
// Constructor Injection
public Client(GreetingService greetingService) {
this.greetingService = greetingService;
}
public void showGreeting() {
greetingService.greet();
}
}
Spring Configuration with Constructor Injection (XML):
<bean id="greetingService" class="com.example.GreetingServiceImpl"/>
<bean id="client" class="com.example.Client">
<constructor-arg ref="greetingService"/>
</bean>
Spring Configuration with Constructor Injection (Java-based):
@Configuration
@ComponentScan("com.example")
public class AppConfig {
@Bean
public Client client() {
return new Client(greetingService());
}
@Bean
public GreetingService greetingService() {
return new GreetingServiceImpl();
}
}
সুবিধা:
- Immutability: কনস্ট্রাক্টরের মাধ্যমে ইনজেকশন করা ডিপেনডেন্সিগুলি অবজেক্ট তৈরির পর পরিবর্তন করা সম্ভব নয়।
- Mandatory Dependencies: যখন নির্দিষ্ট ডিপেনডেন্সি অবশ্যই থাকতে হবে, তখন এটি কার্যকর।
- Clear Dependency Declaration: কনস্ট্রাক্টরের মাধ্যমে ডিপেনডেন্সিগুলি স্পষ্টভাবে ডিফাইন করা থাকে, যা কোডের রিডেবিলিটি বাড়ায়।
2. Setter Injection
Setter Injection হল একটি পদ্ধতি যেখানে ডিপেনডেন্সি setter methods মাধ্যমে ইনজেক্ট করা হয়। এতে কনস্ট্রাক্টর তৈরি না করেও ডিপেনডেন্সি ইনজেকশন করা সম্ভব, যা আপনাকে একাধিক ডিপেনডেন্সি ইনজেক্ট করার সুবিধা দেয়। তবে, এটি কিছু সময়ের জন্য দুর্বল হতে পারে কারণ এখানে ডিপেনডেন্সিগুলি অবজেক্ট তৈরি হওয়ার পর পরিবর্তনযোগ্য থাকে।
উদাহরণ:
// Service Interface
public interface GreetingService {
void greet();
}
// Service Implementation
public class GreetingServiceImpl implements GreetingService {
@Override
public void greet() {
System.out.println("Hello, Welcome to Setter Injection!");
}
}
// Client Class
public class Client {
private GreetingService greetingService;
// Setter Injection
public void setGreetingService(GreetingService greetingService) {
this.greetingService = greetingService;
}
public void showGreeting() {
greetingService.greet();
}
}
Spring Configuration with Setter Injection (XML):
<bean id="greetingService" class="com.example.GreetingServiceImpl"/>
<bean id="client" class="com.example.Client">
<property name="greetingService" ref="greetingService"/>
</bean>
Spring Configuration with Setter Injection (Java-based):
@Configuration
@ComponentScan("com.example")
public class AppConfig {
@Bean
public Client client() {
Client client = new Client();
client.setGreetingService(greetingService());
return client;
}
@Bean
public GreetingService greetingService() {
return new GreetingServiceImpl();
}
}
সুবিধা:
- Optional Dependencies: যে ডিপেনডেন্সিগুলি ঐচ্ছিক, সেগুলির জন্য এটি সুবিধাজনক।
- Flexibility: একবার অবজেক্ট তৈরি হলে, setter এর মাধ্যমে ডিপেনডেন্সিগুলি পরিবর্তন করা সম্ভব।
- Decoupling: কোডের মধ্যে কমপ্লেক্সিটি কমানো যায়, কারণ ডিপেনডেন্সি সরবরাহ করার জন্য সরাসরি কনস্ট্রাক্টর কল করা হয় না।
Constructor Injection vs Setter Injection
| Feature | Constructor Injection | Setter Injection |
|---|---|---|
| Dependency immutability | Yes, dependencies are immutable once set | No, dependencies can be changed after object creation |
| Mandatory Dependencies | Ensures that all required dependencies are provided | Dependencies can be optional or delayed |
| Ease of use | More verbose, especially with multiple dependencies | Simpler with multiple optional dependencies |
| Suitability | Recommended when dependencies are required at the time of object creation | Suitable when dependencies are optional or can be changed later |
সারাংশ
Constructor Injection এবং Setter Injection স্প্রিং ডিপেনডেন্সি ইনজেকশনের দুটি প্রধান পদ্ধতি। Constructor Injection একটি ক্লাসের ডিপেনডেন্সিগুলিকে অবজেক্ট তৈরি হওয়ার সময় ইনজেক্ট করে এবং এটি নিরাপদ এবং দৃঢ়ভাবে ডিপেনডেন্সিগুলির মান নির্ধারণ করে। অন্যদিকে, Setter Injection পদ্ধতিটি ইনজেকশনকে লেটার (পরে) স্থানে অনুমোদিত করে এবং এটি ঐচ্ছিক ডিপেনডেন্সির জন্য উপযুক্ত। আপনার অ্যাপ্লিকেশনের চাহিদা অনুসারে, আপনি কোন পদ্ধতি নির্বাচন করবেন তা নির্ভর করে।
Spring Dependency Injection (DI) কী?
Spring Dependency Injection (DI) হলো একটি ডিজাইন প্যাটার্ন যা অবজেক্টগুলোর মধ্যে ডিপেনডেন্সি সম্পর্ক (dependency relationships) ম্যানেজ করতে সহায়তা করে। Spring DI ব্যবহার করে অবজেক্টগুলোকে তাদের প্রয়োজনীয় ডিপেনডেন্সি সরবরাহ করা হয়, অর্থাৎ এক ক্লাসের অবজেক্ট তৈরি করা হয় এবং সেটি অন্য ক্লাসে ইনজেক্ট করা হয়। এটি ম্যানুয়ালি অবজেক্ট তৈরি করার ঝামেলা দূর করে এবং কোডের পুনঃব্যবহারযোগ্যতা, টেস্টেবিলিটি এবং রিডেবিলিটি বাড়ায়।
Spring Framework DI ব্যবহার করে Bean এবং Spring Container এর মধ্যে সম্পর্ক কিভাবে কাজ করে তা বোঝা খুবই গুরুত্বপূর্ণ।
Bean এবং Spring Container এর ভূমিকা
1. Bean কী?
Spring এ, Bean হল একটি অবজেক্ট যা Spring IoC (Inversion of Control) Container দ্বারা পরিচালিত হয়। Spring Container অবজেক্টগুলো তৈরি করে এবং তাদের মধ্যে ডিপেনডেন্সি ইনজেকশন (DI) পরিচালনা করে। প্রতিটি Bean Spring কনটেক্সটের মধ্যে এক একটি অবজেক্ট এবং এটি একটি প্রোগ্রামিং এর ভূমিকা পালন করে।
Bean এর কিছু প্রধান বৈশিষ্ট্য:
- Object Creation: Spring Container Bean এর অবজেক্ট তৈরি করে।
- Dependency Management: Spring Container Bean এর ডিপেনডেন্সি ইনজেক্ট করে।
- Lifecycle Management: Spring Container Bean এর লাইফসাইকেল ম্যানেজ করে, যেমন ইনিশিয়ালাইজেশন এবং ডিসট্রাকশন।
Spring Bean একটি Java ক্লাসের অবজেক্ট হতে পারে, যা একটি Spring IoC Container দ্বারা তৈরি করা হয় এবং ম্যানেজ করা হয়। এই Bean কে Spring XML ফাইল, Java Configuration বা Annotation-based Configuration এর মাধ্যমে কনফিগার করা যায়।
উদাহরণ:
package com.example.model;
public class Car {
private String model;
// Constructor
public Car(String model) {
this.model = model;
}
// Getter and Setter
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public void start() {
System.out.println("The car is starting...");
}
}
এখানে Car ক্লাসটি একটি Bean হতে পারে, যা Spring Container দ্বারা ম্যানেজ করা হবে।
2. Spring Container কী?
Spring Container হলো Spring Framework এর একটি গুরুত্বপূর্ণ অংশ, যা Bean গুলোর সৃষ্টি, কনফিগারেশন এবং ডিপেনডেন্সি ইনজেকশন (DI) ম্যানেজ করে। Spring Container কে IoC Container বা ApplicationContext (তথ্যপূর্ণ Spring কনটেক্সট) বলা হয়। এটি Bean গুলোর সৃষ্টি এবং লাইফসাইকেল পরিচালনা করে এবং যেকোনো Bean এর ডিপেনডেন্সি স্বয়ংক্রিয়ভাবে ইনজেক্ট করে।
Spring Container দুইটি প্রধান উপাদান দিয়ে কাজ করে:
- BeanFactory: এটি Spring Framework এর সবচেয়ে মৌলিক কন্টেইনার, যা নির্দিষ্ট Bean গুলো তৈরি এবং ম্যানেজ করে।
BeanFactoryসাধারনত সহজ এবং লাইটওয়েট হয়, এবং এটি বিশেষত রিসোর্স সীমিত পরিবেশে ব্যবহার করা হয়। - ApplicationContext: এটি
BeanFactoryএর একটি উন্নত সংস্করণ এবং Spring এর অধিকাংশ বাস্তবিক অ্যাপ্লিকেশনে ব্যবহৃত হয়।ApplicationContextফিচারগুলো যেমন ইভেন্ট লিসেনিং, ইন্টারন্যাশনালাইজেশন এবং AOP মডিউল সাপোর্টসহ আরও অনেক সুবিধা প্রদান করে।
Spring Container Bean গুলোর ডিপেনডেন্সি ম্যানেজ করে এবং তাদের মেথড কল বা ফাংশনালিটিগুলি সঠিকভাবে ইনজেক্ট করে।
Spring Bean কনফিগারেশন উদাহরণ (XML Configuration):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Define Bean -->
<bean id="car" class="com.example.model.Car">
<constructor-arg value="Toyota"/>
</bean>
</beans>
এখানে, car Bean কে Spring Container দ্বারা তৈরি এবং ম্যানেজ করা হবে।
3. Dependency Injection (DI) এবং Bean Management
Spring Container Bean গুলোর মধ্যে ডিপেনডেন্সি ইনজেকশন করে। Spring DI সাধারণত তিনটি পদ্ধতিতে করা হয়:
- Constructor Injection: অবজেক্টের কনস্ট্রাক্টর ব্যবহার করে ডিপেনডেন্সি ইনজেক্ট করা হয়।
- Setter Injection: অবজেক্টের Setter মেথডের মাধ্যমে ডিপেনডেন্সি ইনজেক্ট করা হয়।
- Field Injection: সরাসরি Bean এর ফিল্ডে ডিপেনডেন্সি ইনজেক্ট করা হয়।
Constructor Injection উদাহরণ:
package com.example.model;
public class Car {
private Engine engine;
// Constructor Injection
public Car(Engine engine) {
this.engine = engine;
}
public void start() {
engine.ignite();
System.out.println("Car is starting...");
}
}
Engine Bean এবং DI কনফিগারেশন (XML):
<bean id="engine" class="com.example.model.Engine"/>
<bean id="car" class="com.example.model.Car">
<constructor-arg ref="engine"/>
</bean>
এখানে, Car Bean এর কনস্ট্রাক্টর মেথডে Engine Bean ইনজেক্ট করা হচ্ছে। Spring Container এই ইনজেকশন ম্যানেজ করবে।
4. Spring Bean এর LifeCycle
Spring Bean এর লাইফসাইকেল শুরু হয় যখন Spring Container Bean তৈরি করে এবং শেষ হয় যখন Spring Container সেই Bean কে ডিস্ট্রয় করে। Spring Bean এর লাইফসাইকেল সাধারণত নিম্নলিখিত ধাপগুলো অনুসরণ করে:
- Bean Instantiation: Bean কে Spring Container ইনস্ট্যান্সিয়েট করে।
- Dependency Injection: Spring Container Bean এর ডিপেনডেন্সি ইনজেক্ট করে।
- Bean Initialization: Bean কে ইনিশিয়ালাইজ করা হয়।
- Bean Destruction: Bean কে ধ্বংস করা হয় (যতটা প্রয়োজন হয়)।
5. Spring Bean Scope
Spring Beans এর কিছু Scope থাকে যা Bean এর জীবনের সময়কাল নির্ধারণ করে:
- Singleton Scope: একটি Bean শুধুমাত্র একবার তৈরি হয় এবং Spring Container তা পুনঃব্যবহার করে।
- Prototype Scope: Spring Container প্রতি অনুরোধে নতুন Bean তৈরি করে।
- Request Scope: প্রতিটি HTTP রিকোয়েস্টে নতুন Bean তৈরি হয়।
- Session Scope: HTTP সেশন অনুযায়ী Bean তৈরি হয়।
- Global Session Scope: সার্ভার সেশন অনুযায়ী Bean তৈরি হয় (WebSphere/Portlet এ ব্যবহৃত হয়)।
সারাংশ
Spring DI এর মধ্যে Bean এবং Spring Container এর ভূমিকা অত্যন্ত গুরুত্বপূর্ণ। Bean হলো Spring Container দ্বারা ম্যানেজ করা অবজেক্ট এবং Spring Container হলো সেই পরিবেশ যেখানে Bean গুলো তৈরি, ম্যানেজ এবং ডিপেনডেন্সি ইনজেকশন করা হয়। Spring এর মূল উদ্দেশ্য হল Dependency Injection এর মাধ্যমে কোডকে সহজ, পুনঃব্যবহারযোগ্য, এবং টেস্টযোগ্য করা। Spring Container Bean গুলোর Lifecycle, Scope, এবং Dependency Management সঠিকভাবে পরিচালনা করে।
ডিপেনডেন্সি ইনজেকশন (Dependency Injection - DI) কী?
ডিপেনডেন্সি ইনজেকশন (DI) একটি ডিজাইন প্যাটার্ন যা অবজেক্টগুলির মধ্যে ডিপেনডেন্সি সম্পর্ক (অথবা অন্য অবজেক্টগুলির প্রয়োজনীয়তা) পরিচালনা করার জন্য ব্যবহৃত হয়। এতে একটি অবজেক্ট তার ডিপেনডেন্সি বা প্রয়োজনীয় অবজেক্টগুলো সরাসরি তৈরি না করে, সেগুলো বাহ্যিকভাবে ইনজেক্ট করা হয়। স্প্রিং ফ্রেমওয়ার্কে ডিপেনডেন্সি ইনজেকশন একটি মূল ধারণা, যা কোডের নমনীয়তা, পুনরায় ব্যবহারযোগ্যতা, এবং টেস্টেবিলিটি উন্নত করতে সাহায্য করে।
স্প্রিং DI অবজেক্টগুলিকে একে অপরের উপর নির্ভরশীল করার পরিবর্তে, তাদের মধ্যে সম্পর্ক বা ডিপেনডেন্সি বাহ্যিকভাবে ইনজেক্ট করে, যার ফলে কোডের পরিবর্তন করা সহজ হয়ে ওঠে এবং অ্যাপ্লিকেশনের মডুলারিটি বৃদ্ধি পায়।
ডিপেনডেন্সি ইনজেকশনের ধরন
স্প্রিং DI প্রধানত তিনটি ধরনের ইনজেকশন সমর্থন করে:
- Constructor Injection
- Setter Injection
- Field Injection
1. Constructor Injection
Constructor Injection-এ একটি অবজেক্টের ডিপেনডেন্সি কনস্ট্রাকটরের মাধ্যমে ইনজেক্ট করা হয়। এটি DI এর একটি ক্লাসিক পদ্ধতি এবং নিরাপদ, কারণ কনস্ট্রাকটর ইনজেকশনে ডিপেনডেন্সি গুলি নির্ধারিত সময়েই ইনজেক্ট করা হয়, তাই এটি immutable হয়।
উদাহরণ:
public class UserService {
private UserRepository userRepository;
// Constructor Injection
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void addUser(User user) {
userRepository.save(user);
}
}
public class UserRepository {
public void save(User user) {
System.out.println("User saved!");
}
}
এখানে UserService ক্লাসে UserRepository একটি ডিপেনডেন্সি, যা কনস্ট্রাকটরের মাধ্যমে ইনজেক্ট করা হয়েছে।
Spring Configuration (XML):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="userRepository" class="com.example.UserRepository"/>
<bean id="userService" class="com.example.UserService">
<constructor-arg ref="userRepository"/>
</bean>
</beans>
এখানে, UserService Bean এর কনস্ট্রাকটরের মাধ্যমে UserRepository Bean ইনজেক্ট করা হয়েছে।
2. Setter Injection
Setter Injection-এ ডিপেনডেন্সি সেটার মেথডের মাধ্যমে ইনজেক্ট করা হয়। এটি কনস্ট্রাকটর ইনজেকশনের চেয়ে একটু নমনীয়, কারণ এখানে ডিপেনডেন্সি পরিবর্তনযোগ্য হয় এবং সরাসরি সেটার মেথডের মাধ্যমে ডিপেনডেন্সি ইনজেক্ট করা যায়।
উদাহরণ:
public class UserService {
private UserRepository userRepository;
// Setter Injection
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void addUser(User user) {
userRepository.save(user);
}
}
এখানে setUserRepository মেথডের মাধ্যমে UserRepository ইনজেক্ট করা হয়েছে।
Spring Configuration (XML):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="userRepository" class="com.example.UserRepository"/>
<bean id="userService" class="com.example.UserService">
<property name="userRepository" ref="userRepository"/>
</bean>
</beans>
এখানে, UserService Bean এর userRepository প্রপার্টির মাধ্যমে UserRepository Bean ইনজেক্ট করা হয়েছে।
3. Field Injection
Field Injection-এ DI সরাসরি ক্লাসের ফিল্ডে (প্রপার্টি) ইনজেক্ট করা হয়, কোন গেটার বা সেটার মেথড ছাড়াই। যদিও এটি খুবই সহজ এবং কোড লেখা কমিয়ে দেয়, তবে সাধারণভাবে এটি খুবই দুর্বল এবং টেস্টিংয়ের জন্য উপযুক্ত নয়, কারণ এটি ডিপেনডেন্সির জন্য ক্লাসের ফিল্ডে সরাসরি ইনজেকশনের উপর নির্ভরশীল।
উদাহরণ:
public class UserService {
@Autowired
private UserRepository userRepository;
public void addUser(User user) {
userRepository.save(user);
}
}
Spring Configuration (XML):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="userRepository" class="com.example.UserRepository"/>
<bean id="userService" class="com.example.UserService"/>
</beans>
এখানে, @Autowired অ্যানোটেশন ব্যবহার করে UserRepository Bean UserService ক্লাসে সরাসরি ইনজেক্ট করা হয়েছে।
স্প্রিং ডিপেনডেন্সি ইনজেকশন এর সুবিধা
- কোডের নমনীয়তা বৃদ্ধি: DI ব্যবহার করে ক্লাসগুলির মধ্যে ডিপেনডেন্সি ইনজেক্ট করা হলে, ক্লাসগুলির মধ্যে যেকোনো পরিবর্তন সহজে করা সম্ভব হয় এবং কোডের নমনীয়তা বৃদ্ধি পায়।
- টেস্টিং সহজ হয়: DI ব্যবহার করে অবজেক্টগুলির মধ্যে ডিপেনডেন্সি বাইন্ড করা হয়, যার ফলে টেস্টিং সহজ হয়, কারণ ডিপেনডেন্সি মক বা স্টাব করা যেতে পারে।
- কোড রিইউজেবিলিটি: DI প্রভাবিত অ্যাপ্লিকেশন কোডে এক্সটেনশান এবং রিইউজেবিলিটি বাড়াতে সাহায্য করে, কারণ এটি ক্লাসগুলির মধ্যে সম্পর্ক ম্যানেজ করে।
- বৈশিষ্ট্য পরিবর্তন করা সহজ: ডিপেনডেন্সি ইনজেকশন ব্যবহৃত হলে, কোনো ক্লাসের বৈশিষ্ট্য বা ডিপেনডেন্সি সহজেই পরিবর্তন করা যায় এবং সিস্টেমের অবশিষ্ট অংশে প্রভাব না ফেলতে পারে।
সারাংশ
স্প্রিং ডিপেনডেন্সি ইনজেকশন (DI) একটি গুরুত্বপূর্ণ ডিজাইন প্যাটার্ন যা অবজেক্টগুলির মধ্যে ডিপেনডেন্সি সম্পর্ক পরিচালনা করতে ব্যবহৃত হয়। স্প্রিং ফ্রেমওয়ার্কে DI এর মাধ্যমে কোডের নমনীয়তা, টেস্টেবিলিটি, এবং রিইউজেবিলিটি বৃদ্ধি পায়। DI ব্যবহারের জন্য তিনটি প্রধান পদ্ধতি হলো Constructor Injection, Setter Injection, এবং Field Injection। এর মধ্যে, Constructor Injection নিরাপদ এবং সুপারিশকৃত পদ্ধতি, তবে অন্যান্য পদ্ধতিও নির্দিষ্ট পরিস্থিতিতে ব্যবহৃত হতে পারে।
Read more