Guice (Google's Dependency Injection Framework) ডিপেন্ডেন্সি ইনজেকশনের মাধ্যমে Java অ্যাপ্লিকেশনগুলির মধ্যে ক্লাসের মধ্যে loose coupling নিশ্চিত করতে সাহায্য করে। Guice-এর দুটি গুরুত্বপূর্ণ ধারণা হলো Injector এবং Binding, যেগুলি DI (Dependency Injection) সিস্টেমের মূল কাঠামো তৈরি করে।
Injector: Guice এর Dependency Injection এর কেন্দ্রীয় অংশ
Injector হল Guice-এর একটি কোর ক্লাস যা ডিপেন্ডেন্সি ইনজেকশন পরিচালনা করে। এটি ক্লাসের ইনস্ট্যান্স তৈরি করে এবং তাদের প্রয়োজনীয় ডিপেন্ডেন্সি সরবরাহ করে। Injector-কে আপনি Guice-এ getInstance() মেথড ব্যবহার করে একটি অবজেক্ট তৈরি করতে বলেন, এবং Injector তখন সেই অবজেক্টের জন্য ডিপেন্ডেন্সি প্রদান করে।
Injector এর মূল কাজ:
- ডিপেন্ডেন্সি ইনজেকশন: Injector প্রয়োজনীয় ডিপেন্ডেন্সি ইনজেক্ট করে এবং অবজেক্ট তৈরি করে।
- কনফিগারেশন মডিউল ব্যবহার: Guice মডিউল (যা bindings রাখে) Injector-কে কনফিগারেশন প্রদান করে, যাতে Injector জানে কীভাবে ডিপেন্ডেন্সি ইনজেক্ট করতে হবে।
Injector এর উদাহরণ:
import com.google.inject.*;
class Dependency {
public void perform() {
System.out.println("Dependency is being performed!");
}
}
class Service {
private final Dependency dependency;
// Constructor Injection
@Inject
public Service(Dependency dependency) {
this.dependency = dependency;
}
public void execute() {
dependency.perform();
}
}
public class GuiceInjectorExample {
public static void main(String[] args) {
// Guice Injector তৈরি
Injector injector = Guice.createInjector();
// Service ক্লাসের ইনস্ট্যান্স তৈরি করে Dependency Inject করা
Service service = injector.getInstance(Service.class);
service.execute(); // Output: Dependency is being performed!
}
}
উপরের উদাহরণে, Injector Service ক্লাসের ইনস্ট্যান্স তৈরি করে এবং তার Dependency ইনজেক্ট করে।
Binding: Guice-এ Dependency মেপিং
Binding হল Guice-এ একটি নির্দিষ্ট ক্লাস বা ইন্টারফেসের জন্য ডিপেন্ডেন্সি সংজ্ঞায়িত করার প্রক্রিয়া। Guice-এ binding-এর মাধ্যমে, আপনি জানিয়ে দেন যে একটি ইন্টারফেস বা ক্লাসের জন্য কোন বাস্তব ইমপ্লিমেন্টেশন ব্যবহার করা হবে।
Binding কনফিগারেশন:
Guice-এ আপনি AbstractModule ক্লাসের configure() মেথডে bindings কনফিগার করতে পারেন। bind() মেথড ব্যবহার করে আপনি নির্দিষ্ট ইন্টারফেস বা ক্লাসের জন্য ইমপ্লিমেন্টেশন মাপ করুন।
Binding এর উদাহরণ:
import com.google.inject.*;
interface PaymentService {
void processPayment();
}
class CreditCardPaymentService implements PaymentService {
public void processPayment() {
System.out.println("Processing payment through Credit Card!");
}
}
class PaymentModule extends AbstractModule {
@Override
protected void configure() {
// PaymentService ইন্টারফেসের জন্য CreditCardPaymentService ক্লাসের binding
bind(PaymentService.class).to(CreditCardPaymentService.class);
}
}
class PaymentProcessor {
private final PaymentService paymentService;
// Constructor Injection
@Inject
public PaymentProcessor(PaymentService paymentService) {
this.paymentService = paymentService;
}
public void executePayment() {
paymentService.processPayment();
}
}
public class GuiceBindingExample {
public static void main(String[] args) {
// Guice Injector তৈরি এবং মডিউল ইনজেক্ট করা
Injector injector = Guice.createInjector(new PaymentModule());
// PaymentProcessor ইনস্ট্যান্স তৈরি
PaymentProcessor paymentProcessor = injector.getInstance(PaymentProcessor.class);
paymentProcessor.executePayment(); // Output: Processing payment through Credit Card!
}
}
এখানে, Binding-এর মাধ্যমে PaymentService ইন্টারফেসের জন্য CreditCardPaymentService ইমপ্লিমেন্টেশনটি সংজ্ঞায়িত করা হয়েছে। Injector এরপর PaymentProcessor ক্লাসের ইনস্ট্যান্স তৈরি করতে পারে, যেখানে PaymentService ইনজেক্ট করা হয়েছে।
Binding-এর প্রকারভেদ
Guice-এ বেশ কয়েকটি ধরণের Binding থাকতে পারে:
To Instance Binding:
এটি একটি নির্দিষ্ট ইনস্ট্যান্স মেনে চলে।bind(Service.class).toInstance(new ServiceImpl());To Class Binding:
এটি একটি ক্লাসের জন্য ইমপ্লিমেন্টেশন নির্দেশ করে।bind(PaymentService.class).to(CreditCardPaymentService.class);To Provider Binding:
এটি একটি প্রোভাইডার ব্যবহার করে অবজেক্ট তৈরি করে।bind(PaymentService.class).toProvider(PaymentServiceProvider.class);Scoped Binding (Singleton):
এটি একটি singleton বা নির্দিষ্ট লাইফসাইকেল ব্যবহার করে।bind(Service.class).in(Singleton.class);
Injector এবং Binding এর মধ্যে সম্পর্ক
- Injector হল একটি অবজেক্ট যা ডিপেন্ডেন্সি ইনজেকশন পরিচালনা করে এবং ইন্টারফেস/ক্লাসের জন্য সঠিক ইমপ্লিমেন্টেশন প্রদান করে।
- Binding হল Guice-এ ডিপেন্ডেন্সির মাপিং, যা Guice-কে বলে যে কোন ইন্টারফেস বা ক্লাসের জন্য কোন ইমপ্লিমেন্টেশন বা ইনস্ট্যান্স ব্যবহার করতে হবে।
- Injector এবং Binding একে অপরের সাথে কাজ করে: Injector ডিপেন্ডেন্সি ইনজেক্ট করতে
Bindingএর উপর নির্ভর করে।
- Injector Guice-এ ডিপেন্ডেন্সি ইনজেকশনের প্রধান অংশ এবং এটি ডিপেন্ডেন্সি ইনজেক্ট করার কাজটি সরবরাহ করে।
- Binding Guice-এ নির্দিষ্ট ক্লাস বা ইন্টারফেসের জন্য ডিপেন্ডেন্সি কনফিগার করার জন্য ব্যবহৃত হয়।
- Guice-এ Injector এবং Binding একে অপরের সাথে কাজ করে DI সিস্টেমের কার্যকর ব্যবস্থাপনা নিশ্চিত করে, এবং এটি ডেভেলপারদের loose coupling এবং testability সহজে অর্জন করতে সাহায্য করে।
Injector হল Guice ফ্রেমওয়ার্কের একটি গুরুত্বপূর্ণ কম্পোনেন্ট যা Dependency Injection (DI) প্যাটার্নের মূল কাজটি পরিচালনা করে। Guice-এর মাধ্যমে, Injector হল সেই অবজেক্ট যা ডিপেনডেন্সি ইনজেকশন পরিচালনা করে এবং নির্দিষ্ট ক্লাসের জন্য প্রয়োজনীয় ডিপেনডেন্সি সরবরাহ করে।
Guice-এর Injector এর মূল কাজ হলো নির্দিষ্ট ডিপেনডেন্সি গ্রাফ তৈরি করা এবং সেই গ্রাফের মাধ্যমে ডিপেনডেন্সি ইনজেকশন নিশ্চিত করা। এটি ক্লাসের প্রয়োজনীয় ডিপেনডেন্সি আবিষ্কার করে এবং সেগুলো ইনজেক্ট করে।
Injector এর ভূমিকা
- ডিপেনডেন্সি ইনজেকশন করা:
- Injector হল মূলত সেই অবজেক্ট যা নির্দিষ্ট ক্লাসের ডিপেনডেন্সি তৈরি এবং ইনজেক্ট করে।
- যখন আপনি কোনো ক্লাসের ইনস্ট্যান্স তৈরি করতে চান, Injector সেই ক্লাসের ডিপেনডেন্সি (যেমন: কনস্ট্রাক্টর ইনজেকশন, ফিল্ড ইনজেকশন) যোগ করবে।
- ডিপেনডেন্সি গ্রাফ তৈরি করা:
- Injector Guice-এর Module দ্বারা কনফিগার করা ডিপেনডেন্সির সম্পর্ক (binding) একটি গ্রাফ হিসেবে তৈরি করে।
- এই গ্রাফের সাহায্যে Guice জানে কোন ক্লাস বা ইন্টারফেসকে কোন ইমপ্লিমেন্টেশনে ম্যাপ করা হবে এবং তাদের ডিপেনডেন্সি কীভাবে ইনজেক্ট হবে।
- ডায়নামিক ইনজেকশন:
- Injector ডিপেনডেন্সি ইনজেকশন চলাকালীন সময়ে প্রোগ্রাম্যাটিকভাবে ডিপেনডেন্সি ইনস্ট্যান্স তৈরি করে এবং এগুলো ইনজেক্ট করে।
- Injector ইনজেকশন করার পর ডিপেনডেন্সি গুলোকে প্রয়োজন অনুসারে ব্যবহার করা হয়।
- ডিপেনডেন্সি রেজোলিউশন:
- Injector গুলি প্রয়োজনীয় ডিপেনডেন্সি রেজোল্ভ (resolve) করতে সক্ষম, অর্থাৎ তা জানে কিভাবে প্রতিটি ক্লাসের জন্য প্রয়োজনীয় ডিপেনডেন্সি প্রদান করতে হবে।
- Scopes সাপোর্ট:
- Injector নির্দিষ্ট স্কোপে ডিপেনডেন্সি ম্যানেজ করতে সহায়তা করে, যেমন singleton, prototype ইত্যাদি।
- উদাহরণস্বরূপ, একটি সিঙ্গেলটন স্কোপে ইনজেক্ট করা হলে, Injector একই অবজেক্ট ব্যবহার করবে প্রতিবার ইনজেকশন করার সময়।
Guice Injector এর কাজের পদ্ধতি
Guice-এ Injector কাজ করে Module-এর মাধ্যমে। Module এ ডিপেনডেন্সির সম্পর্ক binding করা হয়, এবং Injector সে সম্পর্ক অনুসারে ডিপেনডেন্সি ইনজেকশন করে।
Injector কাজ করার ধাপ:
Module তৈরি করা:
- Guice ডিপেনডেন্সি সম্পর্কগুলো Module এর মাধ্যমে কনফিগার করে।
- একটি
AbstractModuleক্লাস তৈরি করে সেখানেconfigure()মেথডের মাধ্যমে ডিপেনডেন্সিরbind()করা হয়।
উদাহরণ:
public class AppModule extends AbstractModule { @Override protected void configure() { bind(Service.class).to(ServiceImpl.class); // Binding Service to ServiceImpl } }Injector তৈরি করা:
- Injector তৈরি করতে
Guice.createInjector()মেথড ব্যবহার করা হয়। - Injector সিস্টেমে কনফিগার করা সমস্ত ডিপেনডেন্সি সম্পর্ক ধরে রাখে।
উদাহরণ:
Injector injector = Guice.createInjector(new AppModule());- Injector তৈরি করতে
ডিপেনডেন্সি ইনজেকশন:
- Injector থেকে নির্দিষ্ট ক্লাসের ইনস্ট্যান্স বা ডিপেনডেন্সি ইনজেক্ট করা হয়।
injector.getInstance()মেথডের মাধ্যমে ইনস্ট্যান্স তৈরি করা হয় এবং সেই ক্লাসে ইনজেকশন করা হয়।
উদাহরণ:
Service service = injector.getInstance(Service.class); service.execute();
Guice Injector এর প্রধান সুবিধা
- Loose Coupling (শিথিল সংযোগ):
- Injector Dependency Injection (DI) প্যাটার্ন ব্যবহার করে কোডের মধ্যে মডিউলগুলোর সম্পর্ক শিথিল করে দেয়, যা কোডে low coupling তৈরি করে। ফলে মডিউলগুলোর মধ্যে নির্ভরশীলতা কমে যায়।
- Typesafe DI:
- Guice Injector টাইপ সেফ ইনজেকশন সাপোর্ট করে, অর্থাৎ কম্পাইল টাইমে টাইপ সম্পর্কিত ভুলগুলো ধরা যায়, যা রানটাইমে সমস্যা হতে পারে না।
- ডিপেনডেন্সির সুসংগঠিত ম্যানেজমেন্ট:
- Injector ডিপেনডেন্সির সম্পর্ক একটি কেন্দ্রীয় স্থানে রাখে এবং এই সম্পর্ক সঠিকভাবে পরিচালনা করে। এটি কোডের অন্যান্য অংশের থেকে ডিপেনডেন্সি ম্যানেজমেন্ট আলাদা রাখে।
- Automatic Dependency Resolution:
- Injector ডিপেনডেন্সি রেজোল্ভ করে ইনজেকশন করার সময়, এটি অবজেক্ট তৈরির সাথে সাথে সম্পর্কিত ডিপেনডেন্সি ইনজেক্ট করে।
- Scalability:
- Injector বড় অ্যাপ্লিকেশনগুলোতে ডিপেনডেন্সির দ্রুত এবং কার্যকর ইনজেকশন সাপোর্ট করে, যার ফলে অ্যাপ্লিকেশন স্কেল করতে সহজ হয়।
Injector এর কিছু অন্যান্য বৈশিষ্ট্য
- Scopes:
- Injector বিভিন্ন স্কোপ সাপোর্ট করে (যেমন: Singleton, Request, Session) যা ডিপেনডেন্সির জীবনকাল নিয়ন্ত্রণ করতে সাহায্য করে।
উদাহরণ:
bind(Service.class).in(Singleton.class); // Service Singleton স্কোপে
- Provider Injection:
- Guice-এ আপনি
Providerব্যবহার করে ডিপেনডেন্সি ইনজেক্ট করতে পারেন, যা প্রতি ডিপেনডেন্সি রিকোয়েস্টে নতুন ইনস্ট্যান্স তৈরি করবে। উদাহরণ:
public class MyService { private final Provider<Repository> repositoryProvider; @Inject public MyService(Provider<Repository> repositoryProvider) { this.repositoryProvider = repositoryProvider; } }
- Guice-এ আপনি
- Circular Dependencies:
- Guice এর Injector Circular dependencies এ ভালোভাবে কাজ করতে পারে, তবে এর জন্য সঠিক কনফিগারেশন প্রয়োজন।
Injector Guice-এর একটি মূল কম্পোনেন্ট যা ডিপেনডেন্সি ইনজেকশন পরিচালনা করে। এটি ডিপেনডেন্সির সম্পর্ক কনফিগার করতে এবং সঠিকভাবে ডিপেনডেন্সি ইনজেক্ট করতে ব্যবহৃত হয়। Injector, DI-এর মাধ্যমে কোডের শিথিল সংযোগ, মডুলারিটি এবং টেস্টিং সহজ করে তোলে। Injector ছাড়া Guice বা অন্য DI ফ্রেমওয়ার্কের কার্যকারিতা সম্ভব নয়। Guice Injector, সিস্টেমের ডিপেনডেন্সি গ্রাফ তৈরি করে এবং এই গ্রাফের মাধ্যমে প্রয়োজনীয় ইনস্ট্যান্স ইনজেক্ট করে, যা উন্নত সফটওয়্যার আর্কিটেকচারের জন্য অপরিহার্য।
Guice-এ Binding একটি গুরুত্বপূর্ণ ধারণা, যা নির্ধারণ করে কিভাবে একটি interface এবং তার সংশ্লিষ্ট concrete class কে একে অপরের সাথে যুক্ত (map) করা হবে। এটি Dependency Injection (DI)-এর মূল অংশ, যেখানে interface-এর ইনস্ট্যান্সের জন্য নির্দিষ্ট একটি implementation সরবরাহ করা হয়।
Guice Binding-এর মাধ্যমে Interface এবং Concrete Class এর মধ্যে Mapping করে এবং তখন সেই Mapping অনুযায়ী নির্ভরশীলতাগুলি (dependencies) ইনজেক্ট করা হয়। Guice দুটি প্রধান পদ্ধতি দিয়ে Binding তৈরি করে:
- Interface to Concrete Class Binding
- Named Binding (যতটা প্রয়োজনীয়)
এখানে আমরা Interface to Concrete Class Binding এর উদাহরণ দেখবো।
Interface থেকে Concrete Class এ Binding - উদাহরণ
ধরা যাক, আমাদের একটি Service ইন্টারফেস এবং তার একটি কনক্রিট (Concrete) ইমপ্লিমেন্টেশন ServiceImpl আছে। Guice ব্যবহার করে আমরা কিভাবে Service ইন্টারফেস এবং ServiceImpl ক্লাসের মধ্যে binding তৈরি করতে পারি, সেটি দেখবো।
Step 1: Define the Interface and Concrete Class
public interface Service {
void serve();
}
public class ServiceImpl implements Service {
@Override
public void serve() {
System.out.println("Service is serving...");
}
}
Step 2: Create a Guice Module to Bind Interface to Concrete Class
Guice-এ, Module হল সেই জায়গা যেখানে আমরা Binding সংজ্ঞায়িত করি। আমাদের ক্ষেত্রে, Service ইন্টারফেসকে ServiceImpl ক্লাসের সাথে bind করতে হবে।
import com.google.inject.AbstractModule;
public class AppModule extends AbstractModule {
@Override
protected void configure() {
bind(Service.class).to(ServiceImpl.class); // Service interface mapped to ServiceImpl class
}
}
এখানে, bind(Service.class).to(ServiceImpl.class) এই লাইনটি Guice-কে বলে যে, যখন Service টাইপের ইনস্ট্যান্স প্রয়োজন হবে, তখন ServiceImpl এর ইনস্ট্যান্স প্রদান করবে।
Step 3: Inject the Dependency in the Client Class
এখন, Client ক্লাসে Service ইন্টারফেস ইনজেক্ট করা হবে।
import com.google.inject.Inject;
public class Client {
private final Service service;
@Inject
public Client(Service service) { // Constructor Injection
this.service = service;
}
public void doSomething() {
service.serve();
}
}
এখানে, @Inject অ্যানোটেশনটি Guice-কে বলে যে এটি Service-এর ইনস্ট্যান্স ইনজেক্ট করবে যখন Client ক্লাস তৈরি হবে।
Step 4: Create the Injector and Run the Application
এখন আমাদের Guice Injector তৈরি করতে হবে এবং Client ক্লাসের ইনস্ট্যান্স গ্রহণ করতে হবে।
import com.google.inject.Guice;
import com.google.inject.Injector;
public class Main {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new AppModule()); // Guice Injector with Module
Client client = injector.getInstance(Client.class); // Dependency Injected
client.doSomething(); // This will call ServiceImpl.serve() method
}
}
কোডের কর্মপ্রবাহ:
- AppModule-এ
bind(Service.class).to(ServiceImpl.class)দ্বারা Service ইন্টারফেসকে ServiceImpl ক্লাসের সাথে যুক্ত করা হয়েছে। - Guice Injector তৈরির মাধ্যমে Client ক্লাসের ইনস্ট্যান্স তৈরি করে এবং ইনজেক্টেড Service কে ServiceImpl ক্লাসের ইনস্ট্যান্স হিসেবে ইনজেক্ট করে।
- Client ক্লাসে
service.serve()কল করার মাধ্যমে ServiceImpl ক্লাসেরserve()মেথড কল হয়।
Binding-এ আরও ফিচার এবং কাস্টমাইজেশন
Guice আরও কিছু Advanced Binding ফিচার প্রদান করে:
Named Bindings:
- যদি একাধিক ইমপ্লিমেন্টেশন থাকে, তবে আপনি নাম (name) দিয়ে নির্দিষ্ট করতে পারেন কোন ইমপ্লিমেন্টেশন ব্যবহার করতে হবে।
bind(Service.class).annotatedWith(Names.named("Service1")).to(ServiceImpl.class);Singleton Scope:
- আপনি
@Singletonঅ্যানোটেশন ব্যবহার করে কোনো ইমপ্লিমেন্টেশনকে সিঙ্গেলটন (singleton) হিসেবে চিহ্নিত করতে পারেন, যাতে তার একটিই ইনস্ট্যান্স তৈরি হয়।
bind(Service.class).to(ServiceImpl.class).in(Singleton.class);- আপনি
Provider Bindings:
- আপনি Guice
Providerব্যবহার করে নির্দিষ্ট সময়ে নির্ভরশীলতাগুলি প্রদান করতে পারেন, যা লেজি লোডিং (lazy loading) সক্ষম করে।
bind(Service.class).toProvider(ServiceProvider.class);- আপনি Guice
Guice-এর Binding ব্যবহার করে সহজে Interface এবং তার Concrete Class এর মধ্যে mapping করা যায়, যা loose coupling, testability, এবং maintainability নিশ্চিত করে। এটি কোডের নির্ভরশীলতাগুলিকে কেন্দ্রীয়ভাবে পরিচালনা করতে সহায়ক, এবং বড় অ্যাপ্লিকেশনগুলির ডিপেনডেন্সি ম্যানেজমেন্ট আরও সহজ করে তোলে।
Guice (Dependency Injection Framework) @Inject এবং @Provides এই দুটি গুরুত্বপূর্ণ অ্যানোটেশন ব্যবহার করে নির্ভরশীলতা (dependencies) ইনজেক্ট করতে সাহায্য করে। এগুলির মাধ্যমে, Guice একটি ক্লাসের কনস্ট্রাক্টর, ফিল্ড, অথবা মেথডে ডিপেনডেন্সি ইনজেক্ট করতে পারে, যা কোডের টাইট কপ্লিং কমায় এবং আরও মডুলার, টেস্টেবল অ্যাপ্লিকেশন তৈরি করতে সহায়ক।
@Inject অ্যানোটেশন
@Inject হল Guice-এর একটি অ্যানোটেশন যা একটি ক্লাসের কনস্ট্রাক্টর, ফিল্ড, বা মেথডে ব্যবহার করা হয়, যাতে Guice স্বয়ংক্রিয়ভাবে সেই ডিপেনডেন্সিটি ইনজেক্ট করতে পারে।
কিভাবে কাজ করে:
- Constructor Injection: ডিপেনডেন্সি ইনজেক্ট করতে কনস্ট্রাক্টরে
@Injectব্যবহার করা হয়। - Field Injection: ক্লাসের ফিল্ডে
@Injectব্যবহার করে ডিপেনডেন্সি ইনজেক্ট করা যায়। - Method Injection: মেথডে
@Injectব্যবহার করা হলে, Guice সেই মেথডে ডিপেনডেন্সি ইনজেক্ট করবে।
Constructor Injection Example (@Inject)
import com.google.inject.Inject;
public class BillingService {
private final PaymentService paymentService;
@Inject // Guice will inject PaymentService here
public BillingService(PaymentService paymentService) {
this.paymentService = paymentService;
}
public void processPayment() {
paymentService.pay();
}
}
public interface PaymentService {
void pay();
}
public class PaypalPaymentService implements PaymentService {
@Override
public void pay() {
System.out.println("Payment made via PayPal.");
}
}
Usage:
import com.google.inject.Guice;
import com.google.inject.Injector;
public class Main {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new BillingModule());
BillingService billingService = injector.getInstance(BillingService.class);
billingService.processPayment(); // Output: Payment made via PayPal.
}
}
Explanation:
- Guice
@Injectকনস্ট্রাক্টরেPaymentServiceইনজেক্ট করবে। BillingServiceকনস্ট্রাক্টরটি শুধুমাত্রPaymentService-এর উপর নির্ভরশীল, এবং Guice সেই নির্ভরশীলতাটি সরবরাহ করবে।
Field Injection Example (@Inject)
import com.google.inject.Inject;
public class BillingService {
@Inject // Guice will inject PaymentService here
private PaymentService paymentService;
public void processPayment() {
paymentService.pay();
}
}
Usage:
import com.google.inject.Guice;
import com.google.inject.Injector;
public class Main {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new BillingModule());
BillingService billingService = injector.getInstance(BillingService.class);
billingService.processPayment(); // Output: Payment made via PayPal.
}
}
Explanation:
@Injectফিল্ডে ব্যবহার করা হলে, Guice সরাসরি সেই ফিল্ডে নির্ভরশীলতা ইনজেক্ট করবে।
@Provides মেথড
Guice-এর @Provides অ্যানোটেশন ব্যবহার করে, আপনি বিশেষ ধরনের নির্ভরশীলতা তৈরি করতে পারেন যা Guice-এর @Inject দ্বারা সরাসরি ইনজেক্ট করা যায় না বা যেগুলি কাস্টম কনফিগারেশন প্রয়োজন। এটি সাধারণত চালানো সময় (runtime) নির্ভরশীলতা তৈরি করতে ব্যবহৃত হয়।
@Provides ব্যবহার করা হয় যখন:
- নির্দিষ্ট কনফিগারেশন বা প্যারামিটার প্রয়োজন।
@Injectদ্বারা স্বয়ংক্রিয়ভাবে ইনজেক্ট করা সম্ভব নয়।
@Provides মেথড Example
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;
public class BillingModule extends AbstractModule {
@Override
protected void configure() {
// Other bindings can be configured here if necessary
}
@Provides
@Singleton // This makes sure only one instance of PaymentService is created
public PaymentService providePaymentService() {
return new PaypalPaymentService(); // Custom logic for providing the dependency
}
}
Explanation:
@Providesমেথডের মাধ্যমে আপনি কাস্টম লগিক অনুসারে ডিপেনডেন্সি সরবরাহ করতে পারেন।@Singletonঅ্যানোটেশন ব্যবহার করলে এটি শুধুমাত্র একটি সিঙ্গল ইনস্ট্যান্স প্রদান করবে।
@Inject vs @Provides
| বৈশিষ্ট্য | @Inject | @Provides |
|---|---|---|
| কোথায় ব্যবহার করা হয় | কনস্ট্রাক্টর, ফিল্ড, বা মেথডে | মেথডে |
| কি সরবরাহ করে | Guice সরাসরি নির্ভরশীলতা ইনজেক্ট করে | নির্দিষ্ট কাস্টম লগিকের মাধ্যমে ডিপেনডেন্সি সরবরাহ করে |
| কিভাবে ব্যবহৃত হয় | Guice নিজেই নির্ভরশীলতা সনাক্ত করে এবং ইনজেক্ট করে | আপনাকে কাস্টম @Provides মেথডে নির্ধারণ করতে হয় |
| কোডের পঠনযোগ্যতা | সহজ এবং স্বাভাবিক | কিছুটা জটিল কারণ এটি নির্দিষ্ট মেথডের মাধ্যমে নির্ভরশীলতা সরবরাহ করে |
@Inject এবং @Provides-এর সমন্বিত ব্যবহার
এখন আমরা @Inject এবং @Provides-এর সমন্বয়ে একটি উদাহরণ দেখি।
import com.google.inject.*;
public class BillingService {
private final PaymentService paymentService;
@Inject
public BillingService(PaymentService paymentService) {
this.paymentService = paymentService;
}
public void processPayment() {
paymentService.pay();
}
}
public interface PaymentService {
void pay();
}
public class PaypalPaymentService implements PaymentService {
public void pay() {
System.out.println("Payment made via PayPal.");
}
}
public class BillingModule extends AbstractModule {
@Override
protected void configure() {
bind(PaymentService.class).to(PaypalPaymentService.class);
}
@Provides
@Singleton
public PaymentService providePaymentService() {
return new PaypalPaymentService(); // You can return a custom instance or use other logic
}
}
public class Main {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new BillingModule());
BillingService billingService = injector.getInstance(BillingService.class);
billingService.processPayment(); // Output: Payment made via PayPal.
}
}
@Injectহল Guice-এর প্রাথমিক অ্যানোটেশন যা কনস্ট্রাক্টর, ফিল্ড, এবং মেথডে ডিপেনডেন্সি ইনজেক্ট করতে ব্যবহৃত হয়।@Providesমেথড ব্যবহার করে আপনি কাস্টম ডিপেনডেন্সি সরবরাহ করতে পারেন যেখানে Guice সরাসরি ইনজেক্ট করতে সক্ষম নয়।@Injectএবং@Providesএকসাথে ব্যবহৃত হলে Guice-এর ডিপেনডেন্সি ইনজেকশন ক্ষমতা আরো শক্তিশালী ও নমনীয় হয়।
Guice (গুইস) একটি Dependency Injection (DI) ফ্রেমওয়ার্ক যা Java অ্যাপ্লিকেশনে ডিপেন্ডেন্সি ম্যানেজমেন্ট সহজ করে। Guice বিভিন্ন ধরনের Binding প্রদান করে, যার মাধ্যমে আপনি ক্লাসের ডিপেন্ডেন্সিগুলো ইনজেক্ট করতে পারেন। নিচে তিনটি গুরুত্বপূর্ণ binding প্রকার — Constructor Binding, Linked Binding, এবং Instance Binding — বিস্তারিতভাবে আলোচনা করা হলো।
1. Constructor Binding
Constructor Binding হল Guice-এর একটি পদ্ধতি যার মাধ্যমে আপনি একটি ক্লাসের কন্সট্রাক্টরে ডিপেন্ডেন্সি ইনজেক্ট করতে পারেন। Guice নিশ্চিত করে যে কন্সট্রাক্টরের সমস্ত প্যারামিটার সঠিকভাবে ইনজেক্ট করা হয়েছে এবং সেই কন্সট্রাক্টরটি ব্যবহার করে ক্লাসের একটি ইনস্ট্যান্স তৈরি হবে।
যেভাবে কাজ করে:
- যখন আপনি একটি ক্লাসের ডিপেন্ডেন্সি Inject করতে চান, তখন Guice ঐ ক্লাসের কন্সট্রাক্টরের প্যারামিটারগুলোর জন্য বাইন্ডিং কনফিগারেশন সরবরাহ করে।
- Guice তখন ঐ কন্সট্রাক্টরের প্যারামিটারগুলো ডাইনামিকভাবে ইনজেক্ট করে।
উদাহরণ:
// Service Interface
public interface PaymentService {
void processPayment(String amount);
}
// Implementation
public class CreditCardPaymentService implements PaymentService {
private final String gateway;
// Constructor Injection
public CreditCardPaymentService(String gateway) {
this.gateway = gateway;
}
@Override
public void processPayment(String amount) {
System.out.println("Processing payment of " + amount + " via " + gateway);
}
}
// Guice Module for Constructor Binding
import com.google.inject.AbstractModule;
public class PaymentModule extends AbstractModule {
@Override
protected void configure() {
bind(PaymentService.class)
.to(CreditCardPaymentService.class)
.constructor(String.class); // Binding constructor with String parameter
}
}
// Application
import com.google.inject.Guice;
import com.google.inject.Injector;
public class Application {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new PaymentModule());
PaymentService paymentService = injector.getInstance(PaymentService.class);
paymentService.processPayment("100 USD");
}
}
এই উদাহরণে, CreditCardPaymentService ক্লাসে কন্সট্রাক্টর ইনজেকশন করা হয়েছে এবং String টাইপের প্যারামিটার ইনজেক্ট করার জন্য Guice-কে বলা হয়েছে।
2. Linked Binding
Linked Binding হল Guice-এর আরেকটি পদ্ধতি, যেখানে আপনি একটি ইন্টারফেস বা সুপার ক্লাসকে অন্য কোনো ক্লাসের সাথে সংযুক্ত করেন। এটি আপনাকে একটি ইন্টারফেসের জন্য অনেকগুলো বাস্তবায়ন বা কাস্টম ক্লাস সংজ্ঞায়িত করতে সাহায্য করে।
যেভাবে কাজ করে:
- এই পদ্ধতিতে আপনি একটি ইন্টারফেসকে একটি নির্দিষ্ট ক্লাসের সাথে লিঙ্ক বা বাইন্ড করেন, যেখানে নির্দিষ্ট ক্লাসটি ঐ ইন্টারফেসের জন্য বাস্তবায়ন হিসেবে কাজ করবে।
উদাহরণ:
// Interface
public interface PaymentService {
void processPayment(String amount);
}
// Concrete Implementation
public class CreditCardPaymentService implements PaymentService {
@Override
public void processPayment(String amount) {
System.out.println("Processing credit card payment of: " + amount);
}
}
// Another Implementation
public class PayPalPaymentService implements PaymentService {
@Override
public void processPayment(String amount) {
System.out.println("Processing PayPal payment of: " + amount);
}
}
// Guice Module for Linked Binding
import com.google.inject.AbstractModule;
public class PaymentModule extends AbstractModule {
@Override
protected void configure() {
bind(PaymentService.class)
.to(CreditCardPaymentService.class); // Linked Binding to CreditCardPaymentService
}
}
// Application
import com.google.inject.Guice;
import com.google.inject.Injector;
public class Application {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new PaymentModule());
PaymentService paymentService = injector.getInstance(PaymentService.class);
paymentService.processPayment("100 USD");
}
}
এখানে, PaymentService ইন্টারফেসটি CreditCardPaymentService ক্লাসের সাথে লিঙ্ক বা বাইন্ড করা হয়েছে। যদি আমরা এই লিঙ্কিং পরিবর্তন করতে চাই, তাহলে সহজেই to(PayPalPaymentService.class) সেট করতে পারি।
3. Instance Binding
Instance Binding হল Guice-এর আরেকটি গুরুত্বপূর্ণ বৈশিষ্ট্য যা কোনো নির্দিষ্ট ইনস্ট্যান্সকে বাইন্ড করে। এই পদ্ধতিতে, আপনি একেবারে একটি নির্দিষ্ট অবজেক্ট বা ইনস্ট্যান্স ক্লাসের বাইন্ডিং করে দেন, যার মাধ্যমে Guice ঐ ইনস্ট্যান্সটিকে বিভিন্ন ক্লাসে ইনজেক্ট করবে।
যেভাবে কাজ করে:
- এখানে আপনি সরাসরি একটি নির্দিষ্ট অবজেক্টের ইনস্ট্যান্স Guice-কে প্রদান করেন, যার মাধ্যমে ঐ অবজেক্টটি সব জায়গায় ব্যবহার করা যায়।
উদাহরণ:
// Service Interface
public interface PaymentService {
void processPayment(String amount);
}
// Concrete Implementation
public class CreditCardPaymentService implements PaymentService {
@Override
public void processPayment(String amount) {
System.out.println("Processing payment of: " + amount);
}
}
// Guice Module for Instance Binding
import com.google.inject.AbstractModule;
public class PaymentModule extends AbstractModule {
@Override
protected void configure() {
// Providing a specific instance for PaymentService
bind(PaymentService.class).toInstance(new CreditCardPaymentService());
}
}
// Application
import com.google.inject.Guice;
import com.google.inject.Injector;
public class Application {
public static void main(String[] args) {
Injector injector = Guice.createInjector(new PaymentModule());
PaymentService paymentService = injector.getInstance(PaymentService.class);
paymentService.processPayment("200 USD");
}
}
এখানে, PaymentService এর জন্য আমরা সরাসরি CreditCardPaymentService এর একটি নির্দিষ্ট ইনস্ট্যান্স বাইন্ড করেছি। যখন PaymentService ইনজেক্ট করা হবে, তখন Guice এটি সেই ইনস্ট্যান্সটি সরবরাহ করবে।
সারাংশ:
- Constructor Binding: ডিপেন্ডেন্সিগুলি কন্সট্রাক্টর মাধ্যমে ইনজেক্ট করা হয়।
- Linked Binding: একটি ইন্টারফেস বা সুপার ক্লাসকে নির্দিষ্ট ক্লাসের সাথে লিঙ্ক করা হয়।
- Instance Binding: নির্দিষ্ট একটি ইনস্ট্যান্সকে বাইন্ড করা হয়, যাতে ঐ ইনস্ট্যান্সটি সব জায়গায় ব্যবহার করা যায়।
এই তিনটি Binding পদ্ধতির মাধ্যমে আপনি Guice ফ্রেমওয়ার্কে ডিপেন্ডেন্সি ইনজেকশন খুব সহজে পরিচালনা করতে পারবেন, যা আপনার কোডকে আরো মডুলার এবং রক্ষণাবেক্ষণযোগ্য করে তোলে।
Read more