जावा में डिपेंडेंसी इंजेक्शन: व्यवहार में
\n\nडिपेंडेंसी इंजेक्शन (DI) जावा में आधुनिक विकास के प्रमुख सिद्धांतों में से एक है, जो Spring और Jakarta EE जैसे फ्रेमवर्क का आधार है। इस लेख में हम समझेंगे कि डिपेंडेंसी इंजेक्शन क्या है, इसकी आवश्यकता क्यों है, और सबसे महत्वपूर्ण बात, कोड उदाहरणों के साथ इसे व्यवहार में कैसे लागू किया जाए।
\n\nडिपेंडेंसी इंजेक्शन क्या है और यह क्यों महत्वपूर्ण है?
\n\nडिपेंडेंसी इंजेक्शन एक डिज़ाइन पैटर्न है जिसमें कोई ऑब्जेक्ट अपनी निर्भरताएँ बाहर से प्राप्त करता है, न कि उन्हें स्वयं बनाता है। यह Inversion of Control (IoC) के सिद्धांत को लागू करता है। क्लास के स्वयं अपनी निर्भरताओं को प्रबंधित करने के बजाय, नियंत्रण एक बाहरी कंटेनर या फैक्ट्री को स्थानांतरित कर दिया जाता है।
\n\nकल्पना करें कि आप सूचनाएँ भेजने के लिए एक एप्लिकेशन लिख रहे हैं। DI के बिना, आपका कोड इस तरह दिख सकता है:
\n\npublic class NotificationService {\n private EmailSender emailSender = new EmailSender();\n\n public void send(String message) {\n emailSender.send(message);\n }\n}\n\nसमस्या स्पष्ट है: NotificationService EmailSender से कसकर जुड़ा हुआ है। यदि आप SMS या Push सूचनाएँ जोड़ना चाहते हैं, तो पूरी क्लास को फिर से लिखना होगा। डिपेंडेंसी इंजेक्शन के साथ यह समस्या हल हो जाती है:
public class NotificationService {\n private final MessageSender messageSender;\n\n // निर्भरता कंस्ट्रक्टर के माध्यम से पास की जाती है\n public NotificationService(MessageSender messageSender) {\n this.messageSender = messageSender;\n }\n\n public void send(String message) {\n messageSender.send(message);\n }\n}\n\nअब क्लास किसी विशिष्ट कार्यान्वयन के बजाय एब्स्ट्रैक्शन MessageSender पर निर्भर करता है। यह कोड को लचीला, परीक्षण योग्य और स्केलेबल बनाता है।
जावा में निर्भरता इंजेक्शन के तरीके
\n\nजावा में DI को लागू करने के तीन मुख्य तरीके हैं। आइए प्रत्येक को उदाहरणों के साथ देखें।
\n\n1. कंस्ट्रक्टर इंजेक्शन (Constructor Injection)
\n\nयह सबसे पसंदीदा तरीका है। निर्भरताएँ कंस्ट्रक्टर के पैरामीटर के माध्यम से पास की जाती हैं और आमतौर पर final के रूप में चिह्नित की जाती हैं।
public class UserService {\n private final UserRepository userRepository;\n private final EmailService emailService;\n\n public UserService(UserRepository userRepository, EmailService emailService) {\n this.userRepository = userRepository;\n this.emailService = emailService;\n }\n\n public void registerUser(User user) {\n userRepository.save(user);\n emailService.sendWelcomeEmail(user.getEmail());\n }\n}\n\nलाभ:
\n- \n
- अनिवार्य निर्भरताएँ स्पष्ट रूप से दिखाई देती हैं \n
- ऑब्जेक्ट हमेशा मान्य स्थिति में होता है \n
- अपरिवर्तनीय (immutable) ऑब्जेक्ट के लिए उपयुक्त \n
- परीक्षण करना आसान — बस mock-ऑब्जेक्ट पास करें \n
2. सेटर इंजेक्शन (Setter Injection)
\n\nऑब्जेक्ट बनाने के बाद setter-विधियों के माध्यम से निर्भरताएँ सेट की जाती हैं।
\n\npublic class OrderService {\n private PaymentGateway paymentGateway;\n\n public void setPaymentGateway(PaymentGateway paymentGateway) {\n this.paymentGateway = paymentGateway;\n }\n\n public void processOrder(Order order) {\n paymentGateway.charge(order.getTotal());\n }\n}\n\nकब उपयोग करें: वैकल्पिक निर्भरताओं के लिए या जब ऑब्जेक्ट के जीवनकाल के दौरान निर्भरताएँ बदल सकती हैं। हालाँकि, यह तरीका ऑब्जेक्ट को परिवर्तनीय (mutable) और कम पूर्वानुमानित बनाता है।
\n\n3. फील्ड इंजेक्शन (Field Injection)
\n\nअक्सर फ्रेमवर्क के साथ एनोटेशन के माध्यम से उपयोग किया जाता है, जैसे Spring में @Autowired।
public class ReportService {\n @Autowired\n private DataSource dataSource;\n\n public Report generateReport() {\n return dataSource