Spring এর Dependency Injection (DI)

Java Technologies - স্প্রিং (Spring)
149
149

Dependency Injection (DI) কি?

Dependency Injection (DI) হল একটি ডিজাইন প্যাটার্ন যা একটি অবজেক্টকে তার প্রয়োজনীয় ডিপেনডেন্সি (অন্য অবজেক্ট) সরবরাহ (inject) করে, যাতে এই অবজেক্টটি নিজের ডিপেনডেন্সি তৈরি না করে। সহজভাবে বললে, DI হল একটি প্রক্রিয়া যেখানে অবজেক্টটি নিজে থেকে তার ডিপেনডেন্সি তৈরি না করে, বরং অন্য কোনও কম্পোনেন্ট বা কন্টেইনার (যেমন স্প্রিং কন্টেইনার) তার ডিপেনডেন্সি সরবরাহ করে।

স্প্রিং ফ্রেমওয়ার্ক Dependency Injection (DI) প্রক্রিয়া অনুসরণ করে এবং এটি বিভিন্ন অবজেক্টের মধ্যে সম্পর্ক স্থাপন করতে সাহায্য করে, যার ফলে কোডের নমনীয়তা, পুনঃব্যবহারযোগ্যতা, এবং টেস্টযোগ্যতা বৃদ্ধি পায়।


Spring Framework এ Dependency Injection (DI) এর ধারণা

স্প্রিং কনটেইনার DI ব্যবহার করে অবজেক্টগুলির মধ্যে সম্পর্ক তৈরি করে এবং একটি অবজেক্ট যখন অন্য একটি অবজেক্টের উপর নির্ভরশীল হয় তখন সেই নির্ভরশীলতাগুলি কনটেইনার থেকে ইনজেক্ট করা হয়। এই ইনজেকশনটি স্প্রিং কনটেইনারের মাধ্যমে করা হয়, যা অবজেক্টগুলির জীবনচক্র এবং তাদের ডিপেনডেন্সি পরিচালনা করে।

স্প্রিং DI মূলত তিনটি পদ্ধতিতে কাজ করে:

  1. Constructor-based Injection
  2. Setter-based Injection
  3. Interface-based Injection

Spring Dependency Injection এর প্রধান উপকারিতা:

  1. Loosely Coupled Code: DI এর মাধ্যমে কোডের কম্পোনেন্টগুলি একে অপরের থেকে আলাদা (loosely coupled) হয়ে যায়, ফলে কোডে পরিবর্তন বা আপডেট করা সহজ হয়।
  2. Testability: DI ব্যবহারে টেস্টিং সহজ হয় কারণ আপনি মক (mock) অবজেক্ট বা ফেক (fake) ডিপেনডেন্সি সরবরাহ করতে পারেন।
  3. Maintainability: কোড রক্ষণাবেক্ষণ এবং আপডেট করা সহজ হয় কারণ একে অপরের উপর নির্ভরশীলতা কমিয়ে ফেলা হয়।
  4. Flexibility: DI অ্যাপ্লিকেশন ডিজাইনকে আরও নমনীয় এবং পুনঃব্যবহারযোগ্য করে তোলে।

Spring DI কনফিগারেশন পদ্ধতি:

স্প্রিং ফ্রেমওয়ার্কে DI কনফিগার করার জন্য দুটি প্রধান পদ্ধতি রয়েছে:

  1. XML Configuration: স্প্রিং কনফিগারেশন ফাইল (beans.xml) ব্যবহার করে ডিপেনডেন্সি ইনজেকশন করা হয়।
  2. Annotation-based Configuration: স্প্রিং অ্যানোটেশন (যেমন @Autowired, @Component, ইত্যাদি) ব্যবহার করে ডিপেনডেন্সি ইনজেকশন করা হয়।

Constructor-based Dependency Injection

Constructor-based Dependency Injection এ, কোনো অবজেক্টের ডিপেনডেন্সি কনস্ট্রাক্টরের মাধ্যমে ইনজেক্ট করা হয়। এটি সর্বাধিক ব্যবহৃত এবং সুপারিশকৃত পদ্ধতি কারণ এটি অবজেক্ট তৈরির সময় সমস্ত ডিপেনডেন্সি ইনজেক্ট করে এবং আপনি নিশ্চিত হতে পারেন যে অবজেক্টটি সম্পূর্ণভাবে ইনিশিয়ালাইজড।

উদাহরণ:

import org.springframework.stereotype.Component;

@Component
public class Engine {
    public void start() {
        System.out.println("Engine is starting...");
    }
}

@Component
public class Car {
    private final Engine engine;

    // Constructor-based DI
    public Car(Engine engine) {
        this.engine = engine;
    }

    public void drive() {
        engine.start();
        System.out.println("Car is driving...");
    }
}

এখানে:

  • Car ক্লাসের কনস্ট্রাক্টর Engine অবজেক্টকে ইনজেক্ট করে।
  • স্প্রিং কনটেইনার এই কনস্ট্রাক্টরটি কল করে এবং Engine অবজেক্টটি Car ক্লাসে ইনজেক্ট করে।

XML Configuration (Constructor-based DI)

<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="engine" class="com.example.Engine" />
    <bean id="car" class="com.example.Car">
        <constructor-arg ref="engine" />
    </bean>
</beans>

এখানে:

  • constructor-arg ট্যাগের মাধ্যমে Engine অবজেক্টটি Car এর কনস্ট্রাক্টরে ইনজেক্ট করা হচ্ছে।

Annotation-based Configuration (Constructor-based DI)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Car {

    private final Engine engine;

    @Autowired  // Constructor-based DI
    public Car(Engine engine) {
        this.engine = engine;
    }

    public void drive() {
        engine.start();
        System.out.println("Car is driving...");
    }
}

এখানে:

  • @Autowired অ্যানোটেশন দিয়ে কনস্ট্রাক্টরের মাধ্যমে ডিপেনডেন্সি ইনজেক্ট করা হচ্ছে।

Setter-based Dependency Injection

Setter-based Dependency Injection এ, ডিপেনডেন্সি ইনজেক্ট করার জন্য সেটার মেথড ব্যবহার করা হয়। যদিও এটি একটি সহজ পদ্ধতি, তবে এটি কিছু ক্ষেত্রে কম নিরাপদ হতে পারে, কারণ এটি ঐচ্ছিক (optional) ডিপেনডেন্সি ইনজেকশনকে সমর্থন করে।

উদাহরণ:

import org.springframework.stereotype.Component;

@Component
public class Car {
    private Engine engine;

    // Setter-based DI
    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public void drive() {
        engine.start();
        System.out.println("Car is driving...");
    }
}

এখানে:

  • setEngine() মেথডের মাধ্যমে Engine অবজেক্টটি ইনজেক্ট করা হচ্ছে।

XML Configuration (Setter-based DI)

<bean id="car" class="com.example.Car">
    <property name="engine" ref="engine" />
</bean>

এখানে:

  • property ট্যাগ ব্যবহার করে Engine অবজেক্টটি Car অবজেক্টে ইনজেক্ট করা হচ্ছে।

Annotation-based Configuration (Setter-based DI)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Car {

    private Engine engine;

    @Autowired  // Setter-based DI
    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public void drive() {
        engine.start();
        System.out.println("Car is driving...");
    }
}

এখানে:

  • @Autowired অ্যানোটেশন দিয়ে setEngine() মেথডের মাধ্যমে Engine অবজেক্ট ইনজেক্ট করা হচ্ছে।

Spring DI এর উপকারিতা:

  1. Loose Coupling: DI কোডের মধ্যে কম্পোনেন্টগুলির মধ্যে সম্পর্ককে দুর্বল (loose) করে, যার ফলে এক কম্পোনেন্টের পরিবর্তন অন্যান্য কম্পোনেন্টে প্রভাব ফেলবে না।
  2. Reusability: একবার একটি অবজেক্ট তৈরি হলে সেটি বিভিন্ন স্থানে পুনরায় ব্যবহার করা যায়।
  3. Testability: DI সহজেই টেস্টিং করা যায় কারণ ডিপেনডেন্সিগুলিকে মক বা স্টাব (mock or stub) অবজেক্ট দিয়ে প্রতিস্থাপন করা যায়।
  4. Maintainability: কোড রক্ষণাবেক্ষণ সহজ হয় কারণ পরিবর্তনগুলি কেবলমাত্র ডিপেনডেন্সি ক্লাসে করা যায়, মূল লজিককে স্পর্শ না করে।

সারাংশ

Dependency Injection (DI) হল একটি গুরুত্বপূর্ণ ডিজাইন প্যাটার্ন, যা স্প্রিং ফ্রেমওয়ার্কে অবজেক্টের ডিপেনডেন্সিগুলিকে স্বয়ংক্রিয়ভাবে ইনজেক্ট করার পদ্ধতি। স্প্রিং ফ্রেমওয়ার্ক DI এর মাধ্যমে কোডের নমনীয়তা, পুনঃব্যবহারযোগ্যতা, টেস্টযোগ্যতা, এবং রক্ষণাবেক্ষণযোগ্যতা উন্নত করে। DI কনফিগার করার দুটি প্রধান পদ্ধতি হলো XML configuration এবং Annotation-based configurationConstructor-based এবং Setter-based ইনজেকশন দুটি জনপ্রিয় পদ্ধতি, যেখানে Constructor-based ইনজেকশন সাধারণত সুপারিশকৃত কারণ এটি ডিপেনডেন্সির পূর্ণতা নিশ্চিত করে।

Content added By

Dependency Injection কি এবং এর প্রয়োজনীয়তা

116
116

Dependency Injection (DI) হলো একটি ডিজাইন প্যাটার্ন যা অবজেক্ট নির্মাণের সময় তাদের নির্ভরশীলতা (dependencies) বাইরে থেকে সরবরাহ করার প্রক্রিয়া। Spring Framework এ DI এর মাধ্যমে অ্যাপ্লিকেশনের বিভিন্ন ক্লাসের মধ্যে কম্পোনেন্টগুলো (objects) আলাদা করা হয়, এবং প্রয়োজন অনুসারে তাদের ইন্সট্যান্স তৈরির জন্য Spring কন্টেইনার (Spring IoC Container) সাহায্য করে।

Spring DI এর মাধ্যমে, কোনো ক্লাস বা মডিউল তার নির্ভরশীলতা (যেমন অন্যান্য ক্লাস বা অবজেক্ট) সরাসরি নিজের মধ্যে ইনস্ট্যান্সিয়েট না করে, বরং Spring কন্টেইনার তাকে প্রদান করে। এর ফলে কোডের রক্ষণাবেক্ষণ এবং টেস্টিং আরও সহজ হয়ে যায়।


Dependency Injection এর ধারণা

Dependency Injection এর মূল ধারণা হলো:

  • ক্লাস বা অবজেক্টগুলির মধ্যে নির্ভরশীলতা ইনস্ট্যান্সিয়েট করার দায়িত্ব কন্টেইনারের উপর ছেড়ে দেওয়া।
  • Constructor Injection, Setter Injection, এবং Field Injection — এই তিনটি প্রধান পদ্ধতি দিয়ে DI বাস্তবায়িত করা যায়।

Spring এ DI সাধারণত Inversion of Control (IoC) কন্টেইনারের মাধ্যমে পরিচালিত হয়, যেখানে Spring কন্টেইনার বিভিন্ন অবজেক্ট বা বীন (bean) তৈরি ও পরিচালনা করে।


Dependency Injection এর প্রকারভেদ

১. Constructor Injection

Constructor Injection এ, নির্ভরশীল অবজেক্টগুলো কনস্ট্রাক্টর এর মাধ্যমে ইনজেক্ট করা হয়। এই পদ্ধতিতে, যেকোনো ক্লাসের কনস্ট্রাক্টর প্যারামিটার হিসেবে অন্যান্য নির্ভরশীল অবজেক্টগুলো সরবরাহ করা হয়।

উদাহরণ: Constructor Injection

package com.example.service;

import org.springframework.stereotype.Service;

@Service
public class UserService {
    private final UserRepository userRepository;

    // Constructor Injection
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void getUserDetails() {
        // Use userRepository here
    }
}

এখানে, UserService ক্লাসে UserRepository ইনজেক্ট করা হচ্ছে কনস্ট্রাক্টর এর মাধ্যমে।

২. Setter Injection

Setter Injection এ, নির্ভরশীল অবজেক্টগুলো setter method এর মাধ্যমে ইনজেক্ট করা হয়। Spring কন্টেইনার ক্লাসের setter মেথড কল করে নির্ভরশীলতা সরবরাহ করে।

উদাহরণ: Setter Injection

package com.example.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    private UserRepository userRepository;

    // Setter Injection
    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void getUserDetails() {
        // Use userRepository here
    }
}

এখানে, UserService ক্লাসে UserRepository ইনজেক্ট করা হচ্ছে setter method এর মাধ্যমে। @Autowired অ্যানোটেশন Spring কন্টেইনারকে জানায় যে, এই setter মেথডটি ব্যবহার করে DI করতে হবে।

৩. Field Injection

Field Injection এ, নির্ভরশীলতা সরাসরি ফিল্ড (instance variable) এ ইনজেক্ট করা হয়। এই পদ্ধতিতে setter বা কনস্ট্রাক্টরের পরিবর্তে Spring কন্টেইনার সরাসরি ফিল্ডে ইনজেক্ট করে।

উদাহরণ: Field Injection

package com.example.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository; // Field Injection

    public void getUserDetails() {
        // Use userRepository here
    }
}

এখানে, UserRepository সরাসরি userRepository ফিল্ডে ইনজেক্ট করা হয়েছে @Autowired ব্যবহার করে।


Dependency Injection এর প্রয়োজনীয়তা

১. Loosely Coupled Code (কমপ্লেক্সিটি কমানো)

DI ব্যবহারের মাধ্যমে কোডে loose coupling তৈরি হয়, যার মানে হলো ক্লাসগুলোর মধ্যে সম্পর্ক কমানো হয়। এই ধরনের কোডে, একটি ক্লাস তার নির্ভরশীলতা সরাসরি নিজে তৈরি করে না, বরং এগুলি বাইরের উপাদান দ্বারা সরবরাহ করা হয়। এর ফলে কোড আরও নমনীয় এবং রক্ষণাবেক্ষণযোগ্য হয়।

উদাহরণস্বরূপ, যদি একটি ক্লাস নিজে তার নির্ভরশীল অবজেক্ট তৈরি করে, তবে কোডের মডিফিকেশন করলে প্রতিটি ক্লাসে পরিবর্তন করতে হবে। তবে DI ব্যবহারের মাধ্যমে, শুধুমাত্র এক জায়গায় পরিবর্তন করে অন্যান্য অংশে স্বয়ংক্রিয়ভাবে পরিবর্তন আনা সম্ভব হয়।

২. Testability (টেস্টিং সহজ করা)

DI ব্যবহারের মাধ্যমে আপনি unit testing সহজভাবে করতে পারেন। এটি বিভিন্ন অংশের মধ্যে Dependency Injection ব্যবহারের মাধ্যমে মক (mock) অবজেক্ট প্রদান করতে সক্ষম হয়। এর ফলে আপনি বিভিন্ন অবজেক্টের আচরণ আলাদাভাবে পরীক্ষা করতে পারেন।

যেমন:

public class UserServiceTest {
    
    @Test
    public void testGetUserDetails() {
        UserRepository mockRepo = mock(UserRepository.class);
        UserService userService = new UserService(mockRepo);
        
        // Perform tests on userService
    }
}

এখানে mock(UserRepository.class) ব্যবহার করে UserRepository এর মক অবজেক্ট তৈরি করা হয়েছে, যাতে UserService টেস্ট করা যায়।

৩. Maintainability (রক্ষণাবেক্ষণ সহজ করা)

DI ব্যবহারের মাধ্যমে আপনার অ্যাপ্লিকেশনটি আরও রক্ষণাবেক্ষণযোগ্য হয়ে ওঠে। কোনো ক্লাস বা কম্পোনেন্টে পরিবর্তন আনার জন্য, শুধু নির্ভরশীলতা বদলানো হয় এবং অন্য অংশের কোডে কোনো পরিবর্তন করতে হয় না।

৪. Flexibility (ফ্লেক্সিবিলিটি বৃদ্ধি)

DI ব্যবহারের মাধ্যমে আপনি কোডের ফ্লেক্সিবিলিটি বৃদ্ধি করতে পারেন। নির্ভরশীলতা কখনও সহজে পরিবর্তন বা পরীক্ষার জন্য পরিবর্তিত হতে পারে, কারণ বিভিন্ন ধরনের ইমপ্লিমেন্টেশন নির্ভরশীলতা সরবরাহ করা সম্ভব হয়।

৫. Clear Separation of Concerns (ক্লিয়ার সেপারেশন অব কনসার্নস)

DI আপনাকে কোডের দায়িত্ব (concerns) পরিষ্কারভাবে আলাদা করতে সহায়তা করে। এর মাধ্যমে আপনি অ্যাপ্লিকেশনটির বিভিন্ন অংশের কাজ (business logic, database access, UI, etc.) পৃথকভাবে পরিচালনা করতে পারেন।


সারাংশ

Dependency Injection (DI) হল একটি ডিজাইন প্যাটার্ন যা কোডের loose coupling নিশ্চিত করে এবং অ্যাপ্লিকেশনকে নমনীয়, টেস্টযোগ্য এবং রক্ষণাবেক্ষণযোগ্য করে তোলে। Spring Framework DI এর মাধ্যমে আপনি ক্লাসগুলির মধ্যে নির্ভরশীলতা স্বয়ংক্রিয়ভাবে ম্যানেজ করতে পারেন, যেমন Constructor Injection, Setter Injection, এবং Field Injection পদ্ধতি ব্যবহারের মাধ্যমে। এর মাধ্যমে আপনার অ্যাপ্লিকেশনের কোড আরও কার্যকরী এবং সহজেই টেস্ট এবং রক্ষণাবেক্ষণযোগ্য হয়।

DI এর প্রয়োগের মাধ্যমে আপনি cross-cutting concerns সহজে এবং মডুলারভাবে পরিচালনা করতে পারেন, যা অ্যাপ্লিকেশন উন্নয়নকে আরও শক্তিশালী এবং স্থিতিশীল করে তোলে।


Content added By

Constructor Injection এবং Setter Injection এর ব্যবহার

135
135

Spring Framework এর ডিপেনডেন্সি ইনজেকশন (Dependency Injection - DI) একটি গুরুত্বপূর্ণ বৈশিষ্ট্য, যা অবজেক্টগুলির মধ্যে সম্পর্ক পরিচালনা করে এবং তাদের নির্ভরশীলতাগুলি সরবরাহ করে। Spring এ ডিপেনডেন্সি ইনজেকশন করার দুটি প্রধান পদ্ধতি হল Constructor Injection এবং Setter Injection। এই দুটি পদ্ধতির মাধ্যমে আপনি ক্লাসের মধ্যে ডিপেনডেন্সি (অবজেক্টের সম্পর্ক) ইনজেক্ট করতে পারেন।

এই টিউটোরিয়ালে আমরা Constructor Injection এবং Setter Injection এর ব্যবহার এবং তাদের মধ্যে পার্থক্য সম্পর্কে বিস্তারিত আলোচনা করব।


Constructor Injection

Constructor Injection হল ডিপেনডেন্সি ইনজেকশনের একটি পদ্ধতি যেখানে ডিপেনডেন্সি (অবজেক্ট) ক্লাসের কনস্ট্রাক্টরের মাধ্যমে ইনজেক্ট করা হয়। এই পদ্ধতিতে, Spring কনস্ট্রাক্টরের ইনপুট প্যারামিটারগুলির মাধ্যমে ডিপেনডেন্সি প্রদান করে।

সুবিধা:

  1. Immutable Objects: কনস্ট্রাক্টর ইনজেকশন ব্যবহার করলে অবজেক্টটি immutable (অপরিবর্তনীয়) হয়, অর্থাৎ একবার সেট করা হলে ডিপেনডেন্সি পরিবর্তন করা যায় না।
  2. Required Dependencies: সমস্ত প্রয়োজনীয় ডিপেনডেন্সি ইনজেক্ট করা হয়, কারণ কনস্ট্রাক্টর কল করতে হলে সব প্যারামিটারকে প্রোভাইড করতে হবে।
  3. Compile-time checking: কনস্ট্রাক্টর ইনজেকশন ব্যবহার করলে কম্পাইল-টাইমে ডিপেনডেন্সি চেকিং করা সম্ভব হয়।

উদাহরণ: Constructor Injection

@Component
public class EmployeeService {

    private final EmployeeRepository employeeRepository;

    // Constructor Injection
    public EmployeeService(EmployeeRepository employeeRepository) {
        this.employeeRepository = employeeRepository;
    }

    public void saveEmployee(Employee employee) {
        employeeRepository.save(employee);
    }
}

@Component
public class EmployeeRepository {
    public void save(Employee employee) {
        System.out.println("Employee saved: " + employee.getName());
    }
}

এখানে:

  • EmployeeService ক্লাসের কনস্ট্রাক্টরটি EmployeeRepository কে ইনজেক্ট করে।
  • Spring কনটেইনার যখন EmployeeService ক্লাসের একটি অবজেক্ট তৈরি করবে, তখন EmployeeRepository স্বয়ংক্রিয়ভাবে কনস্ট্রাক্টরের মাধ্যমে ইনজেক্ট করা হবে।

Spring Configuration (XML/Java Config):

@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
    // Spring automatic DI will work based on constructor injection
}

এখানে, @Component অ্যানোটেশন দ্বারা Spring জানে যে, এই ক্লাসগুলি Spring Bean হিসেবে ব্যবহার হবে। Spring EmployeeService এর কনস্ট্রাক্টরকে স্বয়ংক্রিয়ভাবে EmployeeRepository ইনজেক্ট করবে।


Setter Injection

Setter Injection হল ডিপেনডেন্সি ইনজেকশনের আরেকটি পদ্ধতি, যেখানে ডিপেনডেন্সি (অবজেক্ট) ক্লাসের setter method এর মাধ্যমে ইনজেক্ট করা হয়। এই পদ্ধতিতে, আপনি setter methods তৈরি করেন, যেগুলোর মাধ্যমে Spring ডিপেনডেন্সি প্রদান করে।

সুবিধা:

  1. Optional Dependencies: যদি কোনো ডিপেনডেন্সি ঐচ্ছিক (optional) হয়, তাহলে সেটার জন্য setter injection সবচেয়ে ভালো।
  2. Flexibility: setter method ব্যবহার করার ফলে অবজেক্ট তৈরির পরে ডিপেনডেন্সি সেট করা যায়, তাই এটি কিছুটা লচিল হতে পারে।

উদাহরণ: Setter Injection

@Component
public class EmployeeService {

    private EmployeeRepository employeeRepository;

    // Setter Injection
    @Autowired
    public void setEmployeeRepository(EmployeeRepository employeeRepository) {
        this.employeeRepository = employeeRepository;
    }

    public void saveEmployee(Employee employee) {
        employeeRepository.save(employee);
    }
}

@Component
public class EmployeeRepository {
    public void save(Employee employee) {
        System.out.println("Employee saved: " + employee.getName());
    }
}

এখানে:

  • setEmployeeRepository মেথডের মাধ্যমে EmployeeRepository ইনজেক্ট করা হয়েছে।
  • Spring @Autowired অ্যানোটেশন দিয়ে setter method কে স্বয়ংক্রিয়ভাবে ইনজেক্ট করবে।

Spring Configuration (XML/Java Config):

@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
    // Spring automatic DI will work based on setter injection
}

এখানে, @Autowired অ্যানোটেশনটি Springকে নির্দেশ দেয় যে এটি ইনজেকশন পয়েন্ট এবং Spring এই setter method এর মাধ্যমে ডিপেনডেন্সি ইনজেক্ট করবে।


Constructor Injection এবং Setter Injection এর মধ্যে পার্থক্য

বৈশিষ্ট্যConstructor InjectionSetter Injection
মেথডকনস্ট্রাক্টর মাধ্যমে ইনজেকশনSetter মেথড মাধ্যমে ইনজেকশন
ডিপেনডেন্সিসব ডিপেনডেন্সি আবশ্যক (required dependencies)কিছু ডিপেনডেন্সি ঐচ্ছিক হতে পারে
অবজেক্টের পরিবর্তনএকবার ইনজেক্ট করার পর পরিবর্তন করা যায় নাইনজেকশন পরে ডিপেনডেন্সি পরিবর্তন করা সম্ভব
কমপ্লেক্সিটিএকটু কমপ্লেক্স (মেথড প্যারামিটার নিতে হবে)সহজ এবং সহজে পরিবর্তনযোগ্য
পছন্দের পরিস্থিতিযখন ডিপেনডেন্সি অপরিহার্যযখন ডিপেনডেন্সি ঐচ্ছিক বা লেট ইনজেকশন দরকার

সারাংশ

Constructor Injection এবং Setter Injection হল Spring DI (Dependency Injection) এর দুটি গুরুত্বপূর্ণ পদ্ধতি।

  • Constructor Injection ব্যবহার করা হয় যখন আপনি নিশ্চিত চান যে সব ডিপেনডেন্সি ইনজেক্ট হবে এবং এটি অপরিহার্য (required)।
  • Setter Injection ব্যবহার করা হয় যখন কিছু ডিপেনডেন্সি ঐচ্ছিক হতে পারে এবং আপনি মেথডের মাধ্যমে তাদের ইনজেক্ট করতে চান।

Spring Framework এ এই দুটি পদ্ধতি ব্যবহার করে আপনি আপনার ক্লাসের ডিপেনডেন্সিগুলি সরবরাহ করতে পারবেন এবং কার্যকরীভাবে কোডের পুনরাবৃত্তি কমাতে পারবেন।

Content added By

Spring Bean কি এবং Bean Lifecycle

112
112

স্প্রিং ফ্রেমওয়ার্ক একটি শক্তিশালী এবং জনপ্রিয় Java ফ্রেমওয়ার্ক, যা অ্যাপ্লিকেশন ডেভেলপমেন্টে অনেক সুবিধা প্রদান করে। স্প্রিং ফ্রেমওয়ার্কের মূল ধারণাগুলির মধ্যে একটি হল Bean। স্প্রিং Bean এবং এর Lifecycle বুঝতে পারলে স্প্রিং অ্যাপ্লিকেশন ডেভেলপমেন্ট আরও কার্যকরী এবং নিয়ন্ত্রিত হয়।

Spring Bean কি?

স্প্রিং ফ্রেমওয়ার্কে, Bean হল একটি অবজেক্ট যা স্প্রিং কনটেইনার (ApplicationContext বা BeanFactory) দ্বারা তৈরি, কনফিগার এবং ম্যানেজ করা হয়। স্প্রিং Bean হল সেই সমস্ত ক্লাস বা অবজেক্ট, যেগুলো স্প্রিং কনটেইনারের মাধ্যমে ইনস্ট্যান্সিয়েটেড, কনফিগার এবং ম্যানেজ করা হয়। স্প্রিং কনটেইনার একটি IoC (Inversion of Control) কনটেইনার, যা ডিপেন্ডেন্সি ইনজেকশন (DI) পরিচালনা করে এবং অবজেক্টের লাইফ সাইকেল পরিচালনা করে।

স্প্রিং Bean সাধারণত নিম্নলিখিতভাবে কনফিগার করা হয়:

  1. XML Configuration: XML কনফিগারেশন ফাইলে <bean> ট্যাগ ব্যবহার করে Bean কনফিগার করা হয়।
  2. Java Configuration: @Bean অ্যানোটেশন ব্যবহার করে Java ক্লাসে Bean কনফিগার করা হয়।
  3. Annotation-based Configuration: @Component, @Service, @Repository, @Controller অ্যানোটেশন ব্যবহার করে Bean কনফিগার করা হয়।

উদাহরণ:

@Component
public class EmployeeService {
    public void addEmployee() {
        System.out.println("Employee added!");
    }
}

এখানে, EmployeeService ক্লাসটি একটি স্প্রিং Bean হিসেবে কনফিগার করা হয়েছে, কারণ এটি @Component অ্যানোটেশন ব্যবহার করেছে। স্প্রিং কনটেইনার এই Bean কে নিজেই ইনস্ট্যান্সিয়েট করবে এবং ব্যবহারের জন্য প্রস্তুত রাখবে।


Spring Bean Lifecycle

স্প্রিং Bean এর Lifecycle হল একটি Bean এর সৃষ্টি থেকে ধ্বংস হওয়া পর্যন্ত যে সমস্ত পর্যায় অতিক্রম করে, তা বোঝানোর প্রক্রিয়া। স্প্রিং কনটেইনার একটি Bean এর lifecycle নিয়ন্ত্রণ করে, যাতে Bean এর অবস্থা পর্যায়ক্রমে পরিবর্তিত হয়।

স্প্রিং Bean Lifecycle এর গুরুত্বপূর্ণ পর্যায়গুলি হল:

  1. Bean Creation: প্রথমে স্প্রিং কনটেইনার Bean এর একটি ইনস্ট্যান্স তৈরি করে। এটি @Component, @Service, @Repository, @Controller অ্যানোটেশন বা XML কনফিগারেশন দ্বারা নির্ধারিত হয়।
  2. Dependency Injection (DI): স্প্রিং কনটেইনার Bean এর ইনস্ট্যান্স তৈরি করার পর, এতে নির্দিষ্ট ডিপেন্ডেন্সি ইনজেক্ট করে। যেমন অন্য কোন Bean এর ইনস্ট্যান্স বা কনফিগারেশন ভ্যালু।
  3. Post-Initialization: এই পর্যায়ে Bean এর ইনিশিয়ালাইজেশনের পর কিছু অতিরিক্ত কাজ করা হয়। স্প্রিং @PostConstruct অ্যানোটেশন বা InitializingBean ইন্টারফেসের মাধ্যমে এই কাজগুলো করে থাকে।
  4. Bean Destruction: Bean যখন আর প্রয়োজনীয় থাকে না (অথবা অ্যাপ্লিকেশন বন্ধ হয়ে যায়), তখন স্প্রিং কনটেইনার সেই Bean ধ্বংস করে। এটি @PreDestroy অ্যানোটেশন বা DisposableBean ইন্টারফেসের মাধ্যমে করা হয়।

Spring Bean Lifecycle স্টেপ-by-স্টেপ

  1. Bean Instantiation: স্প্রিং কনটেইনার Bean এর একটি নতুন ইনস্ট্যান্স তৈরি করে। এটি সাধারণত Constructor-based Dependency Injection বা Setter-based Dependency Injection ব্যবহার করে করা হয়।
  2. Dependency Injection: যদি Bean-এ কোন ডিপেন্ডেন্সি থাকে (যেমন অন্য Bean), তাহলে স্প্রিং কনটেইনার সেই ডিপেন্ডেন্সিগুলো Bean এ ইনজেক্ট করে।
  3. Post-Initialization (optional):
    • যদি Bean এ কোনো @PostConstruct অ্যানোটেশন থাকে, তখন সেই মেথডটি কল করা হয়।
    • এছাড়া, আপনি InitializingBean ইন্টারফেসও ব্যবহার করতে পারেন যেখানে afterPropertiesSet() মেথডটি কল করা হবে।
  4. Bean is Ready to Use: এখন Bean পুরোপুরি ইনস্ট্যান্সিয়েটেড এবং কনফিগারড, এটি অ্যাপ্লিকেশন দ্বারা ব্যবহারযোগ্য।
  5. Pre-Destroy (optional):
    • যখন Bean ধ্বংসের জন্য প্রস্তুত, তখন @PreDestroy অ্যানোটেশন বা DisposableBean ইন্টারফেসের মাধ্যমে ধ্বংসের জন্য নির্দিষ্ট মেথড কল করা হয়।
    • destroy-method কনফিগারেশন বা @PreDestroy অ্যানোটেশন ব্যবহার করা যেতে পারে।
  6. Bean Destruction: স্প্রিং কনটেইনার Bean ধ্বংস করে এবং সম্পূর্ণ রিসোর্স মুক্ত করে দেয়।

Spring Bean Lifecycle Example

Step 1: Bean with Initialization and Destruction Methods

@Component
public class EmployeeService implements InitializingBean, DisposableBean {

    public void addEmployee() {
        System.out.println("Employee added!");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("EmployeeService Bean initialized!");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("EmployeeService Bean destroyed!");
    }
}

Step 2: Configuration Class

@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
}

Step 3: Main Application

public class MainApplication {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = 
            new AnnotationConfigApplicationContext(AppConfig.class);
        
        // Retrieve Bean from the context
        EmployeeService employeeService = context.getBean(EmployeeService.class);
        
        // Use the Bean
        employeeService.addEmployee();
        
        // Close context to trigger destruction
        context.close();
    }
}

Output:

EmployeeService Bean initialized!
Employee added!
EmployeeService Bean destroyed!

এখানে, afterPropertiesSet() এবং destroy() মেথডগুলি Bean এর লাইফসাইকেলের মধ্যে ইনিশিয়ালাইজেশন এবং ধ্বংসের সময় কার্যকর হয়েছে।


Spring Bean Lifecycle with Annotations

স্প্রিং Bean এর ইনিশিয়ালাইজেশন এবং ধ্বংস প্রক্রিয়া সহজ করার জন্য @PostConstruct এবং @PreDestroy অ্যানোটেশন ব্যবহার করা যায়।

উদাহরণ:

@Component
public class EmployeeService {

    public void addEmployee() {
        System.out.println("Employee added!");
    }

    @PostConstruct
    public void init() {
        System.out.println("EmployeeService Bean initialized!");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("EmployeeService Bean destroyed!");
    }
}

এখানে, @PostConstruct এবং @PreDestroy অ্যানোটেশনগুলো Bean এর লাইফসাইকেলের ইনিশিয়ালাইজেশন এবং ধ্বংস পর্যায়ে কার্যকর হবে।


Bean Scopes

স্প্রিং Bean-এর লাইফসাইকেল বিভিন্ন স্কোপে পরিচালিত হতে পারে। স্প্রিং ফ্রেমওয়ার্কে প্রধানত পাঁচটি Bean Scope থাকে:

  1. Singleton: এটি ডিফল্ট স্কোপ, যেখানে একমাত্র একটি Bean ইনস্ট্যান্স কনটেইনারে থাকে এবং পুরো অ্যাপ্লিকেশন জুড়ে শেয়ার করা হয়।
  2. Prototype: প্রতিবার নতুন Bean ইনস্ট্যান্স তৈরি হয়।
  3. Request: HTTP রিকোয়েস্টের জন্য একটি Bean ইনস্ট্যান্স তৈরি হয়।
  4. Session: HTTP সেশন অনুসারে Bean তৈরি হয়।
  5. Application: অ্যাপ্লিকেশন লাইফসাইকেল চলাকালীন একটি Bean ইনস্ট্যান্স থাকে।
@Bean
@Scope("singleton")  // or "prototype", "request", "session", "application"
public EmployeeService employeeService() {
    return new EmployeeService();
}

উপসংহার

স্প্রিং Bean এবং Bean Lifecycle স্প্রিং কনটেইনারের দ্বারা পরিচালিত হয় এবং এটি কোডের কার্যকারিতা এবং রক্ষণাবেক্ষণ সহজ করতে সহায়তা করে। স্প্রিং Bean এর লাইফসাইকেল সম্পর্কে জানলে আপনি স্প্রিং এর উপর নির্ভরশীল অ্যাপ্লিকেশনকে আরো দক্ষতার সাথে কনফিগার এবং ম্যানেজ করতে পারবেন। Bean Lifecycle এর অন্তর্গত Initialization, Dependency Injection, Post-Initialization, এবং Destruction পর্যায়গুলো নিশ্চিত করে যে, Bean তার নির্দিষ্ট কাজ সঠিকভাবে করবে এবং কনটেইনারে তার প্রয়োজনীয় রিসোর্স মুক্ত হবে।

Content added By

উদাহরণ সহ DI এর ব্যবহার

102
102

Dependency Injection (DI) হলো একটি ডিজাইন প্যাটার্ন, যা স্প্রিং ফ্রেমওয়ার্কের মূল বৈশিষ্ট্যগুলোর মধ্যে একটি। DI-এর মাধ্যমে একটি ক্লাসের নির্ভরশীলতাগুলো (Dependencies) তার বাইরের কোনো উৎস থেকে ইনজেক্ট করা হয়, ফলে কোডটি ডিকাপলড (Decoupled) এবং মডুলার হয়।


DI-এর প্রধান প্রকারভেদ

  1. Constructor Injection: ডিপেনডেন্সি ক্লাসের কনস্ট্রাক্টরের মাধ্যমে ইনজেক্ট করা হয়।
  2. Setter Injection: ডিপেনডেন্সি Setter মেথডের মাধ্যমে ইনজেক্ট করা হয়।
  3. Field Injection: ডিপেনডেন্সি সরাসরি ফিল্ডে ইনজেক্ট করা হয় (Spring Framework 4.3 বা পরবর্তী সংস্করণে সহজলভ্য)।

উদাহরণ: DI-এর ব্যবহার

Step 1: Maven ডিপেনডেন্সি

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.0</version>
</dependency>

Step 2: Service এবং Repository ক্লাস তৈরি

EmployeeRepository.java

@Component
public class EmployeeRepository {

    public String fetchEmployeeData() {
        return "Employee Data from Database";
    }
}

EmployeeService.java

@Component
public class EmployeeService {

    private final EmployeeRepository employeeRepository;

    // Constructor Injection
    @Autowired
    public EmployeeService(EmployeeRepository employeeRepository) {
        this.employeeRepository = employeeRepository;
    }

    public void displayEmployeeData() {
        String data = employeeRepository.fetchEmployeeData();
        System.out.println("Service Layer: " + data);
    }
}

Step 3: Configuration Class তৈরি

AppConfig.java

@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
}

Step 4: মেইন ক্লাস

MainApplication.java

public class MainApplication {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        // DI এর মাধ্যমে EmployeeService Bean পাওয়া
        EmployeeService employeeService = context.getBean(EmployeeService.class);

        employeeService.displayEmployeeData();

        context.close();
    }
}

আউটপুট

Service Layer: Employee Data from Database

DI-এর অন্যান্য পদ্ধতি (Setter এবং Field Injection)

Setter Injection

EmployeeService.java

@Component
public class EmployeeService {

    private EmployeeRepository employeeRepository;

    // Setter Injection
    @Autowired
    public void setEmployeeRepository(EmployeeRepository employeeRepository) {
        this.employeeRepository = employeeRepository;
    }

    public void displayEmployeeData() {
        String data = employeeRepository.fetchEmployeeData();
        System.out.println("Service Layer: " + data);
    }
}

Field Injection

EmployeeService.java

@Component
public class EmployeeService {

    @Autowired
    private EmployeeRepository employeeRepository;

    public void displayEmployeeData() {
        String data = employeeRepository.fetchEmployeeData();
        System.out.println("Service Layer: " + data);
    }
}

ব্যাখ্যা

  1. Constructor Injection:
    • এটি Immutable Dependency-এর জন্য সবচেয়ে ভালো পদ্ধতি।
    • ডিপেনডেন্সিগুলো কনস্ট্রাক্টর প্যারামিটার হিসেবে পাস করা হয়।
  2. Setter Injection:
    • Optional Dependency-এর জন্য কার্যকর।
    • Setter মেথডের মাধ্যমে ডিপেনডেন্সি ইনজেক্ট করা হয়।
  3. Field Injection:
    • সবচেয়ে সহজ এবং দ্রুত পদ্ধতি, তবে এটি টেস্টিংয়ে সীমাবদ্ধতা সৃষ্টি করতে পারে।

উপসংহার

স্প্রিং ফ্রেমওয়ার্কে DI একটি গুরুত্বপূর্ণ ফিচার যা কোডের Coupling কমায় এবং রিইউজেবিলিটি বাড়ায়। Constructor Injection সাধারণত সেরা পদ্ধতি হিসেবে বিবেচিত হয়, তবে নির্ভরশীলতার প্রয়োজন অনুযায়ী Setter এবং Field Injectionও ব্যবহৃত হতে পারে।


Content added By
Promotion