Skill

Guice এবং Custom Annotations

গুইস (Guice) - Java Technologies

312

Guice হল Google-এর তৈরি একটি dependency injection (DI) ফ্রেমওয়ার্ক যা Java অ্যাপ্লিকেশনগুলিতে ডিপেন্ডেন্সি ইনজেকশনের কাজ সহজ এবং কার্যকরভাবে করে। Guice সাধারণত annotations ব্যবহার করে ডিপেন্ডেন্সি ইনজেকশনের কাজ করে থাকে, যেমন @Inject। তবে, আপনি Custom Annotations তৈরি করে Guice-এর ডিপেন্ডেন্সি ইনজেকশন আরও বিশেষায়িত এবং কাস্টমাইজড করতে পারেন।


Custom Annotations এর প্রয়োজনীয়তা

Guice স্বয়ংক্রিয়ভাবে ডিপেন্ডেন্সি ইনজেকশন পরিচালনা করার জন্য @Inject অ্যানোটেশন ব্যবহার করে, তবে কখনও কখনও আপনাকে নিজের custom annotations তৈরি করতে হতে পারে। এটি বিশেষত দরকারি হতে পারে যদি:

  • আপনার অ্যাপ্লিকেশনে নির্দিষ্ট ডিপেন্ডেন্সি সুনির্দিষ্ট ভাবে ইন্ডিকেট করতে চান।
  • বিভিন্ন ধরনের ডিপেন্ডেন্সি ইনজেকশন করতে চান (যেমন, ক্ষেত্র, কনস্ট্রাক্টর, বা মেথড)।
  • একাধিক ইনস্ট্যান্সের জন্য কাস্টম ডিপেন্ডেন্সি নির্ধারণ করতে চান।

Custom Annotations তৈরি করা

Guice-এ custom annotations তৈরি করতে হলে আপনাকে প্রথমে সেই অ্যানোটেশন তৈরি করতে হবে, তারপরে সেটিকে Guice module-এ ব্যবহার করতে হবে। Custom annotations তৈরি করতে আপনাকে @interface ব্যবহার করতে হবে।


Custom Annotations এর উদাহরণ

ধরা যাক, আমরা একটি Database ডিপেন্ডেন্সি তৈরি করতে চাই যেটি শুধুমাত্র একটি নির্দিষ্ট ক্ষেত্রের জন্য ইনজেক্ট করা হবে। এই ক্ষেত্রে একটি custom annotation তৈরি করব যেটি শুধুমাত্র ওই নির্দিষ্ট ক্ষেত্রের জন্য ডিপেন্ডেন্সি ইনজেক্ট করবে।

Step 1: Custom Annotation তৈরি করা

import java.lang.annotation.*;

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomDatabase {
    // Custom annotation for Database Dependency
}

Step 2: Guice Module তৈরি করা

এখন Guice Module তৈরি করা হবে যা Custom Annotation দ্বারা মাপিং করবে এবং নির্দিষ্ট ডিপেন্ডেন্সি ইনজেক্ট করবে।

import com.google.inject.AbstractModule;
import com.google.inject.Provides;

public class DatabaseModule extends AbstractModule {

    @Override
    protected void configure() {
        // Standard bindings can be configured here if necessary
    }

    // Provide method that binds the custom annotation to the database
    @Provides
    @CustomDatabase
    public Database provideDatabase() {
        return new MySQLDatabase();  // Custom Database implementation
    }
}

Step 3: Dependency Classes তৈরি করা

class Database {
    public void connect() {
        System.out.println("Connected to the Database!");
    }
}

class MySQLDatabase extends Database {
    @Override
    public void connect() {
        System.out.println("Connected to MySQL Database!");
    }
}

Step 4: Field Injection with Custom Annotation

এখন, আপনি এই custom annotation ব্যবহার করে Database ডিপেন্ডেন্সি ইনজেক্ট করতে পারেন। আমরা Service ক্লাসে @CustomDatabase অ্যানোটেশন ব্যবহার করব, যেখানে Database ইনজেক্ট করা হবে।

import com.google.inject.Inject;

public class Service {

    @Inject
    @CustomDatabase  // Custom annotation used here
    private Database database;

    public void performAction() {
        database.connect();
        System.out.println("Service action performed");
    }
}

Step 5: Injector ব্যবহার করা

import com.google.inject.*;

public class GuiceCustomAnnotationExample {
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new DatabaseModule());

        // Service ক্লাসের ইনস্ট্যান্স তৈরি এবং CustomDatabase ইনজেক্ট করা হবে
        Service service = injector.getInstance(Service.class);
        service.performAction();
    }
}

Output:

Connected to MySQL Database!
Service action performed

Custom Annotation এর কার্যকারিতা

  • Dependency Resolution: Guice @CustomDatabase অ্যানোটেশন ব্যবহার করে কেবল নির্দিষ্ট ক্ষেত্রের জন্য ডিপেন্ডেন্সি ইনজেক্ট করবে।
  • Reusability: কাস্টম অ্যানোটেশন একাধিক স্থানে ব্যবহার করা যেতে পারে, যেহেতু একাধিক ডিপেন্ডেন্সির জন্য বিভিন্ন কাস্টম অ্যানোটেশন তৈরি করা সম্ভব।
  • Code Clarity: কোড আরও পরিষ্কার এবং পরিচালনা করা সহজ হয়, বিশেষত যখন একই ধরনের ডিপেন্ডেন্সি বিভিন্ন উপায়ে ব্যবহার করতে হয়।

Custom Annotations এর সুবিধা

ফিচারবিবরণ
এনোটেশন দ্বারা নির্দিষ্ট ডিপেন্ডেন্সিGuice অ্যানোটেশন ব্যবহার করে নির্দিষ্ট ডিপেন্ডেন্সি ইনজেক্ট করতে সাহায্য করে।
সিম্পল ও ক্লিন কোডকাস্টম অ্যানোটেশন ব্যবহারে কোড সহজ ও পরিষ্কার থাকে।
ইনস্ট্যান্স বাছাই করাএকাধিক ডিপেন্ডেন্সির মধ্যে সঠিক ইনস্ট্যান্স নির্বাচন করা সম্ভব।
ব্যবহার সহজে কাস্টমাইজবিভিন্ন ধরনের কাস্টম ডিপেন্ডেন্সি ইন্সট্যানশিয়েশন খুব সহজে করা যায়।

Custom Annotation এর চ্যালেঞ্জ

  1. Complexity: কাস্টম অ্যানোটেশন ব্যবহারে কোডের জটিলতা বাড়তে পারে, বিশেষত যদি সঠিকভাবে কনফিগার না করা হয়।
  2. Reflection: কাস্টম অ্যানোটেশন ব্যবহার করার সময় reflection এর উপর নির্ভরশীল হওয়ার কারণে পারফরম্যান্স কিছুটা কম হতে পারে।
  3. Extra Configuration: কিছু সময় অতিরিক্ত কনফিগারেশন প্রয়োজন হতে পারে, যেমন মডিউল এবং ডিপেন্ডেন্সি সঠিকভাবে ম্যাপ করা।

Guice এবং Custom Annotations ব্যবহার করে আপনি ডিপেন্ডেন্সি ইনজেকশনের প্রক্রিয়া আরও ফ্লেক্সিবল এবং কাস্টমাইজড করতে পারেন। কাস্টম অ্যানোটেশনগুলি বিভিন্ন ডিপেন্ডেন্সির জন্য বিশেষ নিয়মাবলী এবং আচরণ নির্ধারণ করতে সাহায্য করে, যা কোডকে আরও পরিষ্কার এবং পরিচালনা সহজ করে। তবে, এটি ব্যবহারের সময় কনফিগারেশন এবং পারফরম্যান্স সম্পর্কে সতর্ক থাকতে হবে।

Content added By

Guice Dependency Injection (DI) ফ্রেমওয়ার্কটি সাধারণভাবে annotation-based configuration সমর্থন করে, যা ডিপেনডেন্সি ইনজেকশন সহজ এবং সুসংগঠিত করে। Guice এ custom annotations তৈরি করা সম্ভব, যার মাধ্যমে আপনি নির্দিষ্ট কাজের জন্য ইনজেকশন গুলি কাস্টমাইজ করতে পারেন। উদাহরণস্বরূপ, আপনি একটি নির্দিষ্ট ডিপেনডেন্সি বা মেথড ইনজেকশন বিশেষভাবে চিহ্নিত করার জন্য কাস্টম অ্যানোটেশন তৈরি করতে পারেন।

এখানে আমরা দেখবো কিভাবে Guice-এ custom annotations তৈরি করা যায় এবং তাদের মাধ্যমে ডিপেনডেন্সি ইনজেকশন পরিচালনা করা যায়।


Custom Annotations তৈরি করার প্রক্রিয়া

1. Custom Annotation তৈরি করা

প্রথমে একটি কাস্টম অ্যানোটেশন তৈরি করতে হবে। এটি একটি সিম্পল Java অ্যানোটেশন হবে।

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)  // Annotation will be available at runtime
@Target(ElementType.FIELD)  // This annotation will be used on fields
public @interface MyCustomAnnotation {
}

এই অ্যানোটেশনটি @Retention(RetentionPolicy.RUNTIME) দিয়ে ডিফাইন করা হয়েছে, যার মানে এটি রানটাইমে অ্যাক্সেস করা যাবে। আমরা এটিকে @Target(ElementType.FIELD) দিয়ে ফিল্ডগুলিতে প্রয়োগ করতে পারব।


2. Injector এবং Module তৈরি করা

এখন আমরা Guice Module তৈরি করব, যা আমাদের কাস্টম অ্যানোটেশনকে বাইনড (bind) করবে।

import com.google.inject.AbstractModule;
import com.google.inject.BindingAnnotation;
import com.google.inject.Provides;

public class AppModule extends AbstractModule {
    @Override
    protected void configure() {
        // Bind the custom annotation to a specific class or instance
        bind(Service.class).annotatedWith(MyCustomAnnotation.class).to(ServiceImpl.class);
    }

    @Provides
    @MyCustomAnnotation
    public Service provideService() {
        return new ServiceImpl();  // Custom logic to provide Service instance
    }
}

এখানে, আমরা @MyCustomAnnotation ব্যবহার করে Service ইন্টারফেসের জন্য একটি নির্দিষ্ট ইমপ্লিমেন্টেশন (যেমন ServiceImpl) বাইন্ড করছি।


3. Service এবং ServiceImpl ক্লাস তৈরি করা

এখন আমাদের Service ইন্টারফেস এবং এর ServiceImpl ইমপ্লিমেন্টেশন তৈরি করতে হবে।

public interface Service {
    void execute();
}

public class ServiceImpl implements Service {
    @Override
    public void execute() {
        System.out.println("Service is executing...");
    }
}

এখানে Service একটি ইন্টারফেস এবং ServiceImpl তার বাস্তবায়ন।


4. Injector ব্যবহার করা এবং Custom Annotation দিয়ে ইনজেকশন করা

এখন Injector ব্যবহার করে Service ক্লাসের একটি ইন্সট্যান্স ইনজেক্ট করতে হবে, যেখানে আমাদের কাস্টম অ্যানোটেশন ব্যবহৃত হবে।

import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;

public class Application {

    // Inject the service with custom annotation
    @Inject
    @MyCustomAnnotation
    private static Service service;

    public static void main(String[] args) {
        // Create Injector and get instance of Service
        Injector injector = Guice.createInjector(new AppModule());
        
        // Retrieve the Service instance
        service = injector.getInstance(Service.class);
        service.execute();
    }
}

এখানে, আমরা @MyCustomAnnotation ব্যবহার করে Service কে ইনজেক্ট করছি। Guice Injector তা ডিপেনডেন্সি ইনজেক্ট করে।


কাস্টম অ্যানোটেশন ব্যবহারের সুবিধা

  1. Contextual Injection:
    • কাস্টম অ্যানোটেশন ব্যবহারের মাধ্যমে আপনি নির্দিষ্ট কনটেক্সট বা অবস্থায় ডিপেনডেন্সি ইনজেক্ট করতে পারেন। যেমন, একটি বিশেষ মডিউল বা স্কোপে ডিপেনডেন্সি ইনজেক্ট করা।
  2. Type-Safe Binding:
    • Guice এর কাস্টম অ্যানোটেশন ব্যবহার করে আপনি টাইপ সেফ ইনজেকশন পেতে পারেন, কারণ এটি আপনাকে সঠিকভাবে কোন ক্লাসের বা ডিপেনডেন্সির জন্য অ্যানোটেশন ইনজেক্ট করতে সহায়তা করে।
  3. Flexibility:
    • কাস্টম অ্যানোটেশন ব্যবহার করার মাধ্যমে, আপনি ডিপেনডেন্সি ইনজেকশনকে আরও কাস্টমাইজড এবং বিস্তারিতভাবে কনফিগার করতে পারবেন, যা সাধারণ DI পদ্ধতির বাইরে আরও ভালো ফলাফল দিতে পারে।
  4. Cleaner Code:
    • অ্যানোটেশন ব্যবহার করে আপনি কোডের কাঠামো পরিষ্কার রাখতে পারবেন এবং কনফিগারেশন ফাইল বা কোডের মাপ বেশি জটিল না হওয়া নিশ্চিত করতে পারবেন।

কাস্টম অ্যানোটেশন তৈরির আরও কিছু উদাহরণ

  1. Prototype Scoped Annotations:
    • আপনি যদি বিভিন্ন ডিপেনডেন্সি স্কোপ নির্ধারণ করতে চান, তাহলে কাস্টম অ্যানোটেশন ব্যবহার করে prototype বা singleton স্কোপ তৈরি করতে পারেন।
  2. Service Types:
    • আপনি যদি আপনার অ্যাপ্লিকেশনে বিভিন্ন ধরনের Service ইনজেক্ট করতে চান (যেমন, ProductionService এবং MockService), তাহলে আপনি কাস্টম অ্যানোটেশন ব্যবহার করে এগুলো আলাদা করতে পারেন।

Guice তে Custom Annotations ব্যবহার করার মাধ্যমে আপনি আপনার ডিপেনডেন্সি ইনজেকশন প্রক্রিয়া আরও সহজ, রিডেবল এবং কাস্টমাইজড করতে পারেন। কাস্টম অ্যানোটেশন ডিপেনডেন্সি ব্যবস্থাপনাকে আরও ক্লিন এবং মডুলার করতে সহায়ক। Guice এর সাথে এই ধরনের অ্যানোটেশন ব্যবহারে আপনি কাস্টম ডিপেনডেন্সি এবং বিভিন্ন স্কোপ এবং টাইপ সেফ ডিপেনডেন্সি ইনজেকশন তৈরি করতে পারবেন।

Content added By

Guice Dependency Injection (DI) ফ্রেমওয়ার্কে @Inject এবং @Named অ্যানোটেশন দুটি গুরুত্বপূর্ণ ভূমিকা পালন করে। এই অ্যানোটেশনগুলি নির্ভরশীলতাগুলি ইনজেক্ট করতে সাহায্য করে এবং কোডের আরও নমনীয়তা (flexibility) প্রদান করে।


@Inject এর ব্যবহার

@Inject অ্যানোটেশন Guice এর মাধ্যমে ডিপেনডেন্সি ইনজেকশন করার জন্য ব্যবহৃত হয়। এটি constructor, method, অথবা field-এ ইনজেকশন বাস্তবায়ন করতে পারে। যখন আপনি @Inject ব্যবহার করেন, Guice স্বয়ংক্রিয়ভাবে নির্ভরশীলতার ইনস্ট্যান্স তৈরি করে এবং তা সরবরাহ করে।

Constructor Injection এর মাধ্যমে @Inject এর ব্যবহার

import com.google.inject.Inject;

public class Client {
    private final Service service;

    // @Inject অ্যানোটেশন দিয়ে constructor-এ ডিপেনডেন্সি ইনজেক্ট করা হচ্ছে
    @Inject
    public Client(Service service) {
        this.service = service;
    }

    public void doSomething() {
        service.serve();
    }
}

এখানে, @Inject অ্যানোটেশনটি Guice-কে বলে যে Service ইনস্ট্যান্সটি Client ক্লাসের কনস্ট্রাক্টরে ইনজেক্ট করতে হবে।

Field Injection এর মাধ্যমে @Inject এর ব্যবহার

import com.google.inject.Inject;

public class Client {
    @Inject
    private Service service; // @Inject এর মাধ্যমে ফিল্ডে ডিপেনডেন্সি ইনজেক্ট করা হচ্ছে

    public void doSomething() {
        service.serve();
    }
}

এখানে, @Inject ব্যবহার করা হয়েছে ফিল্ডে, যেটি Guice-কে বলে যে service ফিল্ডে ডিপেনডেন্সি ইনজেক্ট করতে হবে।


@Named এর ব্যবহার

@Named অ্যানোটেশন Guice-এর named binding সুবিধা প্রদান করে। এটি বিভিন্ন ইমপ্লিমেন্টেশন বা ইনস্ট্যান্সের মধ্যে ডিপেনডেন্সি নির্বাচন করার জন্য ব্যবহার করা হয়। @Named নামক অ্যানোটেশনটি ব্যবহার করে আপনি একাধিক ইমপ্লিমেন্টেশন বা ভিন্ন কনফিগারেশন ডিপেনডেন্সি ইনজেক্ট করতে পারেন। এটি যখন আপনার কাছে একাধিক সম্ভাব্য ইমপ্লিমেন্টেশন থাকে, তখন আপনি নির্দিষ্ট একটি ইমপ্লিমেন্টেশন নির্বাচন করতে পারবেন।

@Named এর মাধ্যমে Named Binding

ধরা যাক, আপনার কাছে Service ইন্টারফেসের দুটি আলাদা ইমপ্লিমেন্টেশন রয়েছে, এবং আপনি প্রতিটির জন্য আলাদা নাম ব্যবহার করতে চান।

public interface Service {
    void serve();
}

public class ServiceImpl1 implements Service {
    @Override
    public void serve() {
        System.out.println("Service 1 is serving...");
    }
}

public class ServiceImpl2 implements Service {
    @Override
    public void serve() {
        System.out.println("Service 2 is serving...");
    }
}

এখন, @Named অ্যানোটেশন ব্যবহার করে এই দুটি ইমপ্লিমেন্টেশনকে আলাদা করে bind করা যাবে।

Guice Module এ Named Binding

import com.google.inject.AbstractModule;
import com.google.inject.name.Names;

public class AppModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(Service.class).annotatedWith(Names.named("Service1")).to(ServiceImpl1.class);
        bind(Service.class).annotatedWith(Names.named("Service2")).to(ServiceImpl2.class);
    }
}

এখানে, Service ইন্টারফেসের দুটি ইমপ্লিমেন্টেশনকে দুটি আলাদা নাম দেওয়া হয়েছে, Service1 এবং Service2। এখন আপনি @Named ব্যবহার করে নির্দিষ্ট করে একটি ইমপ্লিমেন্টেশন ইনজেক্ট করতে পারবেন।

@Named এর মাধ্যমে Dependency Injection

import com.google.inject.Inject;
import com.google.inject.name.Named;

public class Client {
    private final Service service;

    // @Named এর মাধ্যমে নির্দিষ্ট ইমপ্লিমেন্টেশন ইনজেক্ট করা হচ্ছে
    @Inject
    public Client(@Named("Service1") Service service) {
        this.service = service;
    }

    public void doSomething() {
        service.serve(); // এটি ServiceImpl1 এর serve method কল করবে
    }
}

এখানে, @Named("Service1") ব্যবহার করে ServiceImpl1 কে নির্দিষ্টভাবে ইনজেক্ট করা হয়েছে। একইভাবে, যদি আপনি @Named("Service2") ব্যবহার করেন, তবে ServiceImpl2 ইনজেক্ট হবে।


@Inject এবং @Named একসাথে ব্যবহার

যখন আপনি একাধিক ইমপ্লিমেন্টেশন বা ডিপেনডেন্সি প্রদান করতে চান, তখন আপনি @Inject এবং @Named অ্যানোটেশন দুটি একসাথে ব্যবহার করতে পারেন।

উদাহরণ: @Inject এবং @Named একসাথে ব্যবহার

import com.google.inject.Inject;
import com.google.inject.name.Named;

public class Client {
    private final Service service1;
    private final Service service2;

    @Inject
    public Client(@Named("Service1") Service service1, @Named("Service2") Service service2) {
        this.service1 = service1;
        this.service2 = service2;
    }

    public void doSomething() {
        service1.serve(); // ServiceImpl1
        service2.serve(); // ServiceImpl2
    }
}

এখানে, @Named ব্যবহার করে Service1 এবং Service2 ইমপ্লিমেন্টেশন দুটি আলাদা করে ইনজেক্ট করা হয়েছে।


  • @Inject: Guice-এ ডিপেনডেন্সি ইনজেকশন করতে ব্যবহৃত হয়। এটি constructor, method বা field-এ ইনজেকশন করতে সাহায্য করে। এটি মূলত Guice এর Dependency Injection মেকানিজমের প্রধান অ্যানোটেশন।
  • @Named: একাধিক ইমপ্লিমেন্টেশন থাকলে, এটি নির্দিষ্টভাবে কোন ইমপ্লিমেন্টেশন ইনজেক্ট করতে ব্যবহৃত হয়। এটি বিভিন্ন ডিপেনডেন্সি একে অপরের থেকে আলাদা করে ইনজেক্ট করার সুবিধা প্রদান করে।

উপরের দুটি অ্যানোটেশন ব্যবহার করে আপনি flexibility এবং loose coupling নিশ্চিত করতে পারবেন, যা বড় এবং জটিল অ্যাপ্লিকেশনগুলিতে সুবিধাজনক।

Content added By

Guice-এ, আপনি Custom Annotations তৈরি করে নির্দিষ্ট ডিপেনডেন্সির জন্য কাস্টম Binding তৈরি করতে পারেন। Custom Annotations ব্যবহারের মাধ্যমে আপনি নির্দিষ্ট কনফিগারেশন বা সিস্টেমের জন্য নির্দিষ্ট dependencies ইনজেক্ট করতে পারবেন। Guice-এর @BindingAnnotation অ্যানোটেশনটি ব্যবহার করে কাস্টম অ্যানোটেশন তৈরি করা হয়, যা ডিপেনডেন্সি ইনজেকশনের জন্য qualifier হিসাবে কাজ করে।

কেন Custom Annotations ব্যবহার করবেন?

  • আপনি যখন একটি নির্দিষ্ট ধরনের ডিপেনডেন্সি কনফিগার করতে চান এবং সেই ডিপেনডেন্সি শ্রেণী বা ইন্টারফেসের মধ্যে ভিন্নতা নির্ধারণ করতে চান, তখন কাস্টম অ্যানোটেশন খুবই সহায়ক।
  • এটি বিশেষ ধরনের ডিপেনডেন্সি সরবরাহ করার সময় ডিপেনডেন্সি গুলির মধ্যে বৈশিষ্ট্য বা ভিন্নতা নির্ধারণ করতে পারে।

Custom Annotation তৈরি এবং Binding Example

এখানে আমরা দেখব কিভাবে একটি কাস্টম অ্যানোটেশন তৈরি করে Guice-এর মাধ্যমে ডিপেনডেন্সি Binding করা যায়।

Step 1: Custom Annotation তৈরি করা

প্রথমে, একটি custom annotation তৈরি করতে হবে, যা Guice-এ binding qualifier হিসাবে কাজ করবে।

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import com.google.inject.BindingAnnotation;

@BindingAnnotation // Guice binding qualifier হিসাবে এই অ্যানোটেশনটি চিহ্নিত করা হচ্ছে।
@Retention(RetentionPolicy.RUNTIME) // এই অ্যানোটেশনটি runtime এ পাওয়া যাবে।
public @interface PaypalPayment {
}

এখন আমরা একটি @PaypalPayment নামের কাস্টম অ্যানোটেশন তৈরি করেছি, যেটি Guice-এ পেমেন্ট সার্ভিসের জন্য নির্দিষ্ট binding গুলি চিহ্নিত করবে।


Step 2: Dependency Interface এবং Implementations

এখানে আমরা PaymentService ইন্টারফেস এবং তার দুটি ভিন্ন বাস্তবায়ন তৈরি করব, যেখানে একটিতে @PaypalPayment অ্যানোটেশন ব্যবহার করা হবে।

public interface PaymentService {
    void pay();
}

public class PaypalPaymentService implements PaymentService {
    @Override
    public void pay() {
        System.out.println("Payment made via PayPal.");
    }
}

public class CreditCardPaymentService implements PaymentService {
    @Override
    public void pay() {
        System.out.println("Payment made via Credit Card.");
    }
}
  • এখানে দুটি PaymentService ইমপ্লিমেন্টেশন রয়েছে: PaypalPaymentService এবং CreditCardPaymentService

Step 3: Guice Module-এ Custom Binding তৈরি করা

এখন আমাদের Guice Module তৈরি করতে হবে, যেখানে আমরা কাস্টম অ্যানোটেশন ব্যবহার করে নির্দিষ্ট ডিপেনডেন্সির জন্য binding নির্ধারণ করব।

import com.google.inject.AbstractModule;

public class PaymentModule extends AbstractModule {
    @Override
    protected void configure() {
        // Default Binding for PaymentService
        bind(PaymentService.class).to(CreditCardPaymentService.class);
        
        // Custom Binding using @PaypalPayment annotation
        bind(PaymentService.class).annotatedWith(PaypalPayment.class).to(PaypalPaymentService.class);
    }
}
  • এখানে, bind(PaymentService.class).to(CreditCardPaymentService.class); দ্বারা default binding তৈরি করা হয়েছে, যেখানে কোন কাস্টম অ্যানোটেশন নেই, তবে bind(PaymentService.class).annotatedWith(PaypalPayment.class).to(PaypalPaymentService.class); দিয়ে custom binding তৈরি করা হয়েছে, যা @PaypalPayment অ্যানোটেশনটি ব্যবহার করবে।

Step 4: Guice Injector-এ Custom Annotation ব্যবহার করা

এখন আমরা Guice Injector ব্যবহার করে PaymentService ইন্টারফেসের জন্য নির্দিষ্ট ইমপ্লিমেন্টেশন ইনজেক্ট করতে পারব, যেখানে কাস্টম অ্যানোটেশন ব্যবহার করা হবে।

import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;

public class BillingService {

    private final PaymentService paymentService;

    // Constructor Injection using Custom Annotation @PaypalPayment
    @Inject
    public BillingService(@PaypalPayment PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    public void processPayment() {
        paymentService.pay();
    }

    public static void main(String[] args) {
        // Creating Injector using the PaymentModule
        Injector injector = Guice.createInjector(new PaymentModule());

        // Getting BillingService instance where @PaypalPayment is injected
        BillingService billingService = injector.getInstance(BillingService.class);
        billingService.processPayment(); // Output: Payment made via PayPal.
    }
}

Explanation:

  • BillingService কনস্ট্রাক্টর-এ @PaypalPayment অ্যানোটেশন ব্যবহার করা হয়েছে। এটি Guice-কে নির্দেশ করে যে, PaypalPaymentService ক্লাস ইনজেক্ট করতে হবে।
  • Injector দ্বারা Guice নির্ধারিত PaymentService ইন্টারফেসের জন্য PaypalPaymentService ইনজেক্ট করবে, যেহেতু আমরা @PaypalPayment অ্যানোটেশন দিয়ে কাস্টম binding তৈরি করেছি।

Step 5: Output

Payment made via PayPal.

এখানে, BillingService PaypalPaymentService ইনজেক্ট করেছে, কারণ আমরা @PaypalPayment অ্যানোটেশন ব্যবহার করে সেটি Guice-এ কাস্টমভাবে bind করেছি।


Guice Custom Annotations এর সুবিধা

  • Qualifier হিসাবে ব্যবহার: কাস্টম অ্যানোটেশন Guice-এ ডিপেনডেন্সি ইনজেকশনে qualifier হিসাবে কাজ করতে পারে। এটি একই টাইপের বিভিন্ন ইমপ্লিমেন্টেশনকে আলাদা করে।
  • Code Readability: কাস্টম অ্যানোটেশন ব্যবহার করলে কোডের পাঠযোগ্যতা বৃদ্ধি পায় এবং ডিপেনডেন্সির সাথে কাজ করার সময় স্পষ্টতা বজায় থাকে।
  • Dynamic Bindings: আপনি কাস্টম অ্যানোটেশন ব্যবহার করে বিভিন্ন অবস্থায় ডিপেনডেন্সি dynamically bind করতে পারেন।

  • Custom Annotations Guice-এ খুবই শক্তিশালী এবং নমনীয় dependency management তৈরি করতে সাহায্য করে।
  • @BindingAnnotation অ্যানোটেশন ব্যবহার করে qualifier annotations তৈরি করা যায়, যা একই ধরনের ডিপেনডেন্সি গুলিকে আলাদা করতে সহায়ক।
  • এই পদ্ধতি Guice-এ multiple implementations এর মধ্যে স্পষ্ট পার্থক্য তৈরি করে এবং এটি আরও modular এবং testable কোড লেখায় সহায়ক।
Content added By

Guice (গুইস) ফ্রেমওয়ার্কে এক বা একাধিক Implementation এর জন্য Custom Annotations ব্যবহার করা একটি শক্তিশালী পদ্ধতি। এটি আপনাকে Dependency Injection (DI) কনফিগারেশনকে আরো কাস্টমাইজ এবং নির্দিষ্ট করতে সাহায্য করে। যখন আপনার কাছে একাধিক ইমপ্লিমেন্টেশন থাকে এবং আপনি নির্দিষ্ট কাজের জন্য একটি নির্দিষ্ট ইমপ্লিমেন্টেশন ব্যবহার করতে চান, তখন Custom Annotations খুবই কার্যকর।

Custom Annotations এর প্রয়োজনীয়তা:

কখনও কখনও আপনার কাছে একাধিক Implementation থাকতে পারে যা একই ইন্টারফেস বা সুপার ক্লাস ইমপ্লিমেন্ট করে। সাধারণভাবে, Guice bind() এর মাধ্যমে একটি একক ইমপ্লিমেন্টেশন ব্যবহার করে, কিন্তু আপনি যদি নির্দিষ্ট পরিস্থিতিতে ভিন্ন ইমপ্লিমেন্টেশন ব্যবহার করতে চান, তাহলে Custom Annotations আপনার কাজ সহজ করে।


Custom Annotations এর ব্যবহার:

গুইসে Custom Annotations ব্যবহার করার জন্য, আপনাকে তিনটি মূল স্টেপ অনুসরণ করতে হবে:

  1. Custom Annotation তৈরি করা
  2. Guice Module এ Annotation ব্যবহার করে Binding করা
  3. Injection-এ Custom Annotation ব্যবহার করা

স্টেপ 1: Custom Annotation তৈরি করা

প্রথমে একটি কাস্টম অ্যানোটেশন তৈরি করতে হবে, যা আপনাকে বিভিন্ন ইমপ্লিমেন্টেশন চিহ্নিত করতে সহায়ক হবে।

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import com.google.inject.BindingAnnotation;

@Retention(RetentionPolicy.RUNTIME)
@BindingAnnotation
public @interface CreditCardPayment {
    // Custom annotation for CreditCard payment
}

এই অ্যানোটেশনটি @CreditCardPayment নামে একটি কাস্টম অ্যানোটেশন তৈরি করবে যা BindingAnnotation হিসেবে চিহ্নিত হবে।


স্টেপ 2: Guice Module এ Annotation ব্যবহার করে Binding করা

এখন, আপনি Guice মডিউল তৈরি করবেন যেখানে একাধিক PaymentService ইমপ্লিমেন্টেশনকে কাস্টম অ্যানোটেশন দিয়ে bind করবেন।

import com.google.inject.AbstractModule;
import com.google.inject.name.Names;

public class PaymentModule extends AbstractModule {
    @Override
    protected void configure() {
        // Binding CreditCardPaymentService with a custom annotation
        bind(PaymentService.class)
            .annotatedWith(CreditCardPayment.class)
            .to(CreditCardPaymentService.class);

        // Binding PayPalPaymentService without annotation
        bind(PaymentService.class)
            .to(PayPalPaymentService.class);
    }
}

এখানে, CreditCardPaymentService ক্লাসটি কাস্টম অ্যানোটেশন @CreditCardPayment ব্যবহার করে বাইন্ড করা হয়েছে। অন্যদিকে, PayPalPaymentService বাইন্ডিং সাধারণভাবে করা হয়েছে।


স্টেপ 3: Injection-এ Custom Annotation ব্যবহার করা

এখন, আপনি যেখানে PaymentService ইনজেক্ট করতে চান, সেখানে কাস্টম অ্যানোটেশন ব্যবহার করবেন।

import com.google.inject.Inject;

public class OrderService {
    private final PaymentService paymentService;

    // Injecting PaymentService with CreditCardPayment annotation
    @Inject
    public OrderService(@CreditCardPayment PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    public void placeOrder(String amount) {
        System.out.println("Placing order...");
        paymentService.processPayment(amount);
    }
}

এখানে, OrderService ক্লাসের কন্সট্রাক্টরটি CreditCardPayment অ্যানোটেশন দিয়ে সজ্জিত হয়েছে, যা PaymentService এর নির্দিষ্ট ইমপ্লিমেন্টেশন (CreditCardPaymentService) ইনজেক্ট করবে।


বাকি কোড (Main Method)

এখন Injector তৈরি করে এবং ইনজেক্টেড ক্লাস ব্যবহার করে অ্যাপ্লিকেশন চালাতে হবে।

import com.google.inject.Guice;
import com.google.inject.Injector;

public class Application {
    public static void main(String[] args) {
        // Create Injector with PaymentModule configuration
        Injector injector = Guice.createInjector(new PaymentModule());

        // Get an instance of OrderService
        OrderService orderService = injector.getInstance(OrderService.class);

        // Place an order
        orderService.placeOrder("100 USD");
    }
}

সম্পূর্ণ কোড ব্যাখ্যা:

  1. Custom Annotation: @CreditCardPayment অ্যানোটেশনটি BindingAnnotation হিসেবে চিহ্নিত, যা Guice এর বাইন্ডিং সিস্টেমকে নির্দেশ দেয় কোন ইমপ্লিমেন্টেশনটি কীভাবে ইনজেক্ট হবে।
  2. Guice Module: PaymentModule ক্লাসে বিভিন্ন PaymentService ইমপ্লিমেন্টেশন বাইন্ড করা হয়েছে। CreditCardPaymentService-কে কাস্টম অ্যানোটেশন দিয়ে বাইন্ড করা হয়েছে, অন্যদিকে PayPalPaymentService সাধারণভাবে বাইন্ড করা হয়েছে।
  3. Injection with Custom Annotation: OrderService ক্লাসে কন্সট্রাক্টরের মাধ্যমে @CreditCardPayment অ্যানোটেশন ব্যবহার করে সঠিক ইমপ্লিমেন্টেশন ইনজেক্ট করা হয়েছে।

Custom Annotations এর সুবিধা:

  1. নির্দিষ্ট ইমপ্লিমেন্টেশন নির্বাচন: একাধিক ইমপ্লিমেন্টেশন থাকা সত্ত্বেও কাস্টম অ্যানোটেশন ব্যবহার করে নির্দিষ্ট ইমপ্লিমেন্টেশন নির্বাচন করা সহজ হয়।
  2. বহু বাইন্ডিং নিয়ন্ত্রণ: আপনি একাধিক ইমপ্লিমেন্টেশন সংজ্ঞায়িত করতে পারেন এবং অ্যানোটেশনের মাধ্যমে নির্দিষ্ট ক্লাসে ইনজেক্ট করতে পারেন।
  3. কোডের পরিষ্কারতা এবং সম্প্রসারণযোগ্যতা: কাস্টম অ্যানোটেশন ব্যবহার করার মাধ্যমে কোডের পরিচ্ছন্নতা বজায় থাকে এবং ভবিষ্যতে অন্যান্য ইমপ্লিমেন্টেশন যোগ করা সহজ হয়।
  4. নিরাপত্তা: নির্দিষ্ট ডিপেন্ডেন্সি সরবরাহ নিশ্চিত করার জন্য অ্যানোটেশন ব্যবহার করা হয়, যা ভুল ইনজেকশন এড়াতে সাহায্য করে।

Guice-এ Custom Annotations ব্যবহার করে আপনি একাধিক ইমপ্লিমেন্টেশনের মধ্যে সঠিকটি নির্বাচন করতে পারেন, যা আপনার কোডকে আরও মডুলার, পরিষ্কার এবং টেস্টযোগ্য করে তোলে। এই পদ্ধতি বড় এবং জটিল অ্যাপ্লিকেশনগুলির জন্য খুবই কার্যকর।

Content added By
Promotion

Are you sure to start over?

Loading...