वास्तव में फील्ड इंजेक्शन क्या है और इससे कैसे बचा जाए?


130

मैंने स्प्रिंग एमवीसी और पोर्टलेट्स के बारे में कुछ पोस्ट में पढ़ा कि फील्ड इंजेक्शन की सिफारिश नहीं की जाती है। जैसा कि मैं इसे समझता हूं, जब आप इस तरह से बीन इंजेक्ट करते हैं तो फ़ील्ड इंजेक्शन होता है @Autowired:

@Component
public class MyComponent {
    @Autowired
    private Cart cart;
}

अपने शोध के दौरान मैंने कंस्ट्रक्टर इंजेक्शन के बारे में भी पढ़ा :

@Component
public class MyComponent {
    private final Cart cart;

    @Autowired
    public MyComponent(Cart cart){
       this.cart = cart;
    }
}

इन दोनों प्रकार के इंजेक्शनों के फायदे और नुकसान क्या हैं?


संपादित करें 1: के रूप में इस सवाल का डुप्लिकेट के रूप में चिह्नित किया गया है इस सवाल का मैं यह जाँच। क्योंकि न तो प्रश्न में कोई कोड उदाहरण हैं और न ही उत्तर में यह मेरे लिए स्पष्ट नहीं है कि क्या मैं अपने अनुमान के साथ सही हूं जो इंजेक्शन प्रकार का उपयोग कर रहा हूं।


3
यदि फ़ील्ड-इंजेक्शन उतना ही बुरा है जितना आप वर्णन करते हैं, तो स्प्रिंग इसकी अनुमति क्यों देता है? कोड को अधिक पठनीय और कम क्रिया बनाने में फील्ड इंजेक्शन के अपने फायदे हैं। यदि आप अपने कोडिंग में पर्याप्त अनुशासित हैं, तो आप सुनिश्चित कर सकते हैं कि फील्ड इंजेक्शन का उपयोग करने पर भी चीजें नहीं टूटेंगी।
राख

@ डैश क्योंकि यह उस समय एक साफ सुथरा फीचर था, और निहितार्थ पूरी तरह से नहीं सोचा गया था। वही कारण जो Date(int,int,int)मौजूद है।
चिरलीस -कूटोप्लीटिमिस्टिक-

जवाबों:


225

इंजेक्शन के प्रकार

निर्भरता कैसे एक सेम में इंजेक्ट किया जा सकता है के लिए तीन विकल्प हैं:

  1. एक कंस्ट्रक्टर के माध्यम से
  2. वासियों या अन्य तरीकों के माध्यम से
  3. प्रतिबिंब के माध्यम से, सीधे खेतों में

आप विकल्प 3 का उपयोग कर रहे हैं। यह तब होता है जब आप @Autowiredअपने क्षेत्र पर सीधे उपयोग करते हैं।


इंजेक्शन दिशानिर्देश

एक सामान्य दिशानिर्देश, जिसे स्प्रिंग द्वारा अनुशंसित किया गया है ( कंस्ट्रक्टर-आधारित DI या सेटर-आधारित DI पर अनुभाग देखें ) निम्नलिखित है:

  • अनिवार्य निर्भरता के लिए या अपरिवर्तनीयता के लिए लक्ष्य करते समय, कंस्ट्रक्टर इंजेक्शन का उपयोग करें
  • वैकल्पिक या परिवर्तनशील निर्भरता के लिए, सेटर इंजेक्शन का उपयोग करें
  • ज्यादातर मामलों में फील्ड इंजेक्शन से बचें

फ़ील्ड इंजेक्शन कमियां

फ़ील्ड इंजेक्शन को जिन कारणों से भरा गया है वे निम्नानुसार हैं:

  • आप अपरिवर्तनीय वस्तुओं का निर्माण नहीं कर सकते, जैसा कि आप कंस्ट्रक्टर इंजेक्शन के साथ कर सकते हैं
  • आपकी कक्षाओं में आपके DI कंटेनर के साथ चुस्त युग्मन है और इसका उपयोग बाहर नहीं किया जा सकता है
  • प्रतिबिंब के बिना आपकी कक्षाओं को तत्काल (उदाहरण के लिए इकाई परीक्षणों में) नहीं किया जा सकता है। आपको उन्हें त्वरित करने के लिए DI कंटेनर की आवश्यकता है, जो आपके परीक्षणों को एकीकरण परीक्षणों की तरह बनाता है
  • आपकी वास्तविक निर्भरताएँ बाहर से छिपी हुई हैं और आपके इंटरफ़ेस में परिलक्षित नहीं होती हैं (निर्माणकर्ता या विधियाँ)
  • दस आश्रितों की तरह होना वास्तव में आसान है। यदि आप कंस्ट्रक्टर इंजेक्शन का उपयोग कर रहे हैं, तो आपके पास दस तर्कों के साथ एक निर्माता होगा, जो संकेत देगा कि कुछ गड़बड़ है। लेकिन आप अनिश्चित काल के लिए फ़ील्ड इंजेक्शन का उपयोग करके इंजेक्शन जोड़ सकते हैं। बहुत अधिक निर्भरता होने के कारण एक लाल झंडा है जो आमतौर पर वर्ग एक से अधिक काम करता है, और यह कि एकल जिम्मेदारी सिद्धांत का उल्लंघन हो सकता है।

निष्कर्ष

अपनी आवश्यकताओं के आधार पर, आपको मुख्य रूप से कंस्ट्रक्टर इंजेक्शन या कंस्ट्रक्टर और सेटर इंजेक्शन के कुछ मिश्रण का उपयोग करना चाहिए। फ़ील्ड इंजेक्शन में कई कमियां हैं और इससे बचा जाना चाहिए। फ़ील्ड इंजेक्शन का एकमात्र लाभ यह है कि यह लिखना अधिक सुविधाजनक है, जो सभी विपक्षों को पछाड़ता नहीं है।


आगे की पढाई

मैंने एक ब्लॉग लेख के बारे में लिखा है कि फील्ड इंजेक्शन की आमतौर पर सिफारिश क्यों नहीं की जाती है: फील्ड डिपेंडेंसी इंजेक्शन को हानिकारक माना जाता है


12
यह सामान्य विचार नहीं है और दुनिया को यह बताने के लिए अच्छा नहीं है कि "फील्ड इंजेक्शन से बचा जाना चाहिए"। पेशेवरों और विरोधाभासों को दिखाएं और अन्य लोगों को खुद को तय करने दें;) बहुत से लोगों के पास अन्य अनुभव और चीजों को देखने का अपना तरीका है।
डाइटर

6
यह मामला यहां हो सकता है, लेकिन ऐसे अन्य मामले हैं जहां समुदाय कुछ को हतोत्साहित करने के लिए आम सहमति में आ गया है। उदाहरण के लिए, हंगेरियन नोटेशन को ही लें।
जननिक

आप परीक्षण और निर्भरता दृश्यता के रूप में कुछ अच्छे अंक देते हैं लेकिन मैं सभी से सहमत नहीं हूं। कंस्ट्रक्टर इंजेक्शन में कोई कमियां नहीं हैं? 5 या 6 फ़ील्ड्स को कक्षा में इंजेक्ट करने के लिए जो कॉल की वास्तविक रचनाएं करता है वांछनीय हो सकता है। मैं आपके साथ अपरिहार्यता से भी असहमत हूं। अंतिम क्षेत्र होने के लिए किसी कक्षा को अपरिवर्तनीय होना अनिवार्य नहीं है। यह बेहतर है। जो बहुत अलग है।
davidxxx

मुझे लगता है कि आपका मतलब है "अनिवार्य निर्भरता के लिए या जब अपरिवर्तनीयता के लिए लक्ष्य "
एलेक्स टेरीक्स

1
मैं उस उत्तर की शुरुआत में लिंक करने की बात कर रहा था जो स्प्रिंग डॉक्स से लिंक करता है
Vojtech Ruzicka

47

यह सॉफ्टवेयर विकास में कभी न खत्म होने वाली चर्चाओं में से एक है, लेकिन उद्योग में प्रमुख प्रभावितों ने विषय के बारे में अधिक राय प्राप्त की है और बेहतर विकल्प के रूप में कंस्ट्रक्टर इंजेक्शन का सुझाव देना शुरू कर दिया है।

कंस्ट्रक्टर इंजेक्शन

पेशेवरों:

  • बेहतर परीक्षणशीलता । आपको यूनिट परीक्षणों में किसी भी मॉकिंग लाइब्रेरी या स्प्रिंग संदर्भ की आवश्यकता नहीं है। आप एक ऑब्जेक्ट बना सकते हैं जिसे आप नए कीवर्ड के साथ परीक्षण करना चाहते हैं । इस तरह के परीक्षण हमेशा तेज होते हैं क्योंकि वे प्रतिबिंब तंत्र पर भरोसा नहीं करते हैं। ( यह) 30 मिनट बाद पूछा गया था। अगर लेखक ने कंस्ट्रक्टर इंजेक्शन का इस्तेमाल किया होता तो यह प्रकट नहीं होता)।
  • अपरिवर्तनशीलता । एक बार निर्भरता निर्धारित होने के बाद उन्हें बदला नहीं जा सकता।
  • सुरक्षित कोड । एक कंस्ट्रक्टर के निष्पादन के बाद आपका ऑब्जेक्ट उपयोग करने के लिए तैयार है क्योंकि आप एक पैरामीटर के रूप में पारित किए गए किसी भी चीज को मान्य कर सकते हैं। वस्तु या तो तैयार हो सकती है या नहीं, इसके बीच कोई स्थिति नहीं है। फ़ील्ड इंजेक्शन के साथ आप ऑब्जेक्ट के नाजुक होने पर एक इंटरमीडिएट स्टेप पेश करते हैं।
  • अनिवार्य निर्भरता की स्वच्छ अभिव्यक्ति । इस मामले में फील्ड इंजेक्शन अस्पष्ट है।
  • डेवलपर्स डिजाइन के बारे में सोचते हैं । dit ने 8 पैरामीटर के साथ एक कंस्ट्रक्टर के बारे में लिखा, जो वास्तव में एक खराब डिजाइन का संकेत है और गॉड ऑब्जेक्ट एंटी-पैटर्न है । इससे कोई फर्क नहीं पड़ता कि किसी वर्ग की उसके निर्माता या क्षेत्रों में 8 निर्भरताएं हैं, यह हमेशा गलत है। लोग खेतों की तुलना में एक निर्माता के लिए अधिक निर्भरता जोड़ने के लिए अधिक अनिच्छुक हैं। यह आपके मस्तिष्क के लिए एक संकेत के रूप में काम करता है जिसे आपको कुछ समय के लिए रोकना चाहिए और अपनी कोड संरचना के बारे में सोचना चाहिए।

विपक्ष:

  • अधिक कोड (लेकिन आधुनिक आईडीई दर्द को कम करता है)।

मूल रूप से, क्षेत्र इंजेक्शन विपरीत है।


1
परीक्षणनीयता, हाँ, यह मेरे लिए एक बुरा सपना था कि मैं खेत की फलियों को काट दूं। एक बार, मैंने कॉन्ट्रैक्टर इंजेक्शन का इस्तेमाल किया, मुझे किसी भी तरह का अनावश्यक मजाक नहीं करना चाहिए
केनोबीवान

25

स्वाद की बात। यह आपका निर्णय है।

लेकिन मैं समझा सकता हूं, मैं कंस्ट्रक्टर इंजेक्शन का उपयोग क्यों नहीं करता ।

  1. मैं अपने सभी @Service, @Repositoryऔर @Controllerसेम के लिए एक कंस्ट्रक्टर लागू नहीं करना चाहता । मेरा मतलब है, लगभग 40-50 सेम या अधिक हैं। हर बार अगर मैं एक नया क्षेत्र जोड़ता हूं तो मुझे कंस्ट्रक्टर का विस्तार करना होगा। नहीं, मैं यह नहीं चाहता और मुझे नहीं करना है।

  2. क्या होगा यदि आपके बीन (सेवा या नियंत्रक) को अन्य बीन्स को इंजेक्ट करने के लिए बहुत अधिक आवश्यकता होती है? 4+ मापदंडों वाला एक कंस्ट्रक्टर बहुत बदसूरत है।

  3. अगर मैं CDI का उपयोग कर रहा हूं, तो कंस्ट्रक्टर मुझे चिंतित नहीं करता है।


EDIT # 1 : वोजटेक रूजिका ने कहा:

कक्षा में बहुत अधिक निर्भरताएं हैं और संभवतः एकल जिम्मेदारी सिद्धांत का उल्लंघन कर रही है और इसे फिर से भरना चाहिए

हाँ। सिद्धांत और वास्तविकता। यहाँ एन उदाहरण है: DashboardControllerएकल पथ के लिए मैप किया गया *:8080/dashboard

DashboardControllerडैशबोर्ड / सिस्टम ओवरव्यू पृष्ठ में प्रदर्शित करने के लिए अन्य सेवाओं से मेरा ढेर सारा informations एकत्रित करता है। मुझे इस एकल नियंत्रक की आवश्यकता है। इसलिए मुझे यह केवल एक ही रास्ता (मूल या उपयोगकर्ता भूमिका फ़िल्टर) सुरक्षित करना है।

EDIT # 2 : चूंकि हर कोई कंस्ट्रक्टर में 8 मापदंडों पर केंद्रित है ... यह एक वास्तविक दुनिया का उदाहरण था - एक ग्राहक विरासत कोड। मैंने वह बदल दिया है। वही तर्क मेरे लिए 4+ मापदंडों पर लागू होता है।

यह सभी कोड इंजेक्शन के बारे में है, उदाहरण के लिए निर्माण नहीं।


34
8 निर्भरता के साथ बहुत बदसूरत निर्माता वास्तव में भयानक है क्योंकि यह एक लाल झंडा है कि कुछ गलत है, वर्ग में बहुत अधिक निर्भरता है और शायद एकल जिम्मेदारी सिद्धांत का उल्लंघन कर रहा है और इसे फिर से बनाया जाना चाहिए। यह वास्तव में एक अच्छी बात है।
वोजटेक रुजिका

6
@VojtechRuzicka यह सुनिश्चित करने के लिए अच्छा नहीं है लेकिन कभी-कभी आप इससे बच नहीं सकते हैं।
डायटर

4
मैं 3 के अंगूठे का एक नियम कहूंगा, अकेले 40-50 करने दें, किसी भी वर्ग के लिए निर्भरता एक संकेत होनी चाहिए कि आपको रिफ्लेक्टर की आवश्यकता है। कोई रास्ता नहीं है 40 निर्भरता के साथ एक वर्ग एकल जिम्मेदारी प्रिंसिपल या खुले / करीबी प्रिंसिपल से चिपके हुए है।
अमीन जे

4
@AminJ नियम महान है, लेकिन वास्तविकता अलग है। कंपनी मैं काम कर रहा हूँ 20 साल से अधिक है और हमारे पास बहुत सी विरासत कोड है। रिफैक्टरिंग एक अच्छा विचार है, लेकिन इसमें पैसा खर्च होता है। इसके अलावा मुझे नहीं पता कि यह क्यों कह रहे हैं, लेकिन मेरा मतलब 40-50 निर्भरता नहीं था, मेरा मतलब है 40-50 सेम, घटक, मॉड्यूल ...
डायटर

7
@dit, आपकी स्थिति स्पष्ट रूप से एक है जिसमें तकनीकी ऋण आपको उप-इष्टतम विकल्प बनाने का कारण बन रहा है। अपने शब्दों से, आप ऐसी स्थिति में हैं जहां आपका निर्णय लेने का समय 20 वर्ष से अधिक की विरासत कोड से प्रभावित होता है। जब आप किसी नए प्रोजेक्ट की शुरुआत कर रहे हैं, तो क्या आप कंस्ट्रक्टर इंजेक्शन से अधिक फील्ड इंजेक्शन की सिफारिश करेंगे? हो सकता है कि आपको अपने जवाब में यह बताने के लिए कि आपको फील्ड इंजेक्शन का चुनाव करना है, के लिए एक चेतावनी लिखनी चाहिए।
उमर फारूक ख्वाजा

0

एक और टिप्पणी - वोजटेक रुज़िका ने कहा कि स्प्रिंग ऐसे तीन तरीकों से सेम इंजेक्शन लगाता है (सबसे बड़ी संख्या के साथ उत्तर):

  1. एक कंस्ट्रक्टर के माध्यम से
  2. वासियों या अन्य तरीकों के माध्यम से
  3. प्रतिबिंब के माध्यम से, सीधे खेतों में

यह उत्तर गलत है - क्योंकि हर तरह के इंजेक्शन लगाने के लिए उपयोग किया जाता है! आईडीई का उपयोग करें, सेटर / कंस्ट्रक्टर पर ब्रेकपॉइंट सेट करें, और जांचें।

यह स्वाद का मामला हो सकता है लेकिन यह CASE का मामला भी हो सकता है। जब क्षेत्र इंजेक्शन बेहतर होता है तो @ डिएटर ने एक उत्कृष्ट मामला प्रदान किया। यदि आप स्प्रिंग संदर्भ स्थापित करने वाले एकीकरण परीक्षणों में फ़ील्ड इंजेक्शन का उपयोग कर रहे हैं - वर्ग की परीक्षण क्षमता के साथ तर्क भी अमान्य है - जब तक आप अपने एकीकरण परीक्षणों के परीक्षण पर नहीं लिखना चाहते हैं;)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.