2011-12-30 15 views
7

इस सवाल का जवाब शीर्ष देखें: What exactly is Spring Framework for?वसंत निर्भरता इंजेक्शन क्या हल करता है?

कि समस्या क्या है के रूप में नुकसान में इम, और क्यों स्प्रिंग्स एक एक्सएमएल फ़ाइल के अंदर उपयोग करने के लिए इंटरफ़ेस का क्या कार्यान्वयन को निर्दिष्ट डाल (या एनोटेशन का उपयोग) के समाधान के लिए बेहतर है कोड की एक लाइन होने से बस सही इंटरफ़ेस को तुरंत चालू करें?

संपादित करें: जैसा कि मैंने अपनी एक टिप्पणी में लिखा है, मैं वास्तव में लाभों को समझने की कोशिश कर रहा हूं। मैं समझना चाहता हूं कि क्यों वसंत उपयोगी है। मैं वसंत का उपयोग न करने की वजह से या कारणों को प्रदान करने की कोशिश नहीं कर रहा हूं, बल्कि, मैं कारणों की खोज कर रहा हूं और यह समझने की कोशिश कर रहा हूं कि इसका उपयोग क्यों किया जाना चाहिए। यह पोस्ट बहस को प्रोत्साहित करने के लिए नहीं बल्कि सरल और तकनीकी उत्तरों के लिए थी। मैंने अब सही जवाब के रूप में सबसे छोटा और सबसे चित्रकारी उत्तर चुना है। मुझे कहना होगा कि मुझे आश्चर्य हुआ कि सवाल बंद था।

+0

संभावित डुप्लिकेट: http://stackoverflow.com/questions/871405/why-do-i-need-an-ioc-container-as-opposed-to-straightforward-di-code –

+0

संभावित डुप्लिकेट: http://stackoverflow.com/questions/130794/what-is- निर्भरता- इंजेक्शन –

+0

संबंधित: http://stackoverflow.com/questions/5667801/arguments-against-inversion-of-control-containers/5668093#5668093 –

उत्तर

4

हैं, डि करने के लिए वर्ग बी प्रदान करने की जिम्मेदारी लेता है कक्षा ए। यह आमतौर पर परीक्षण के लिए प्रयोग किया जाता है जहां वसंत एक अलग बी वर्ग प्रदान करेगा (उदाहरण के लिए नकली)।

निश्चित रूप से, आप यह सब स्वयं कर सकते हैं, लेकिन आमतौर पर यदि आप स्प्रिंग (या कोई अन्य डी ढांचा) आपके लिए ऐसा करते हैं तो यह कम काम है।

+1

यदि आप संदर्भ के आधार पर कक्षा में किसी इंटरफ़ेस के विभिन्न कार्यान्वयन का उपयोग करना चाहते हैं, तो आप निर्दिष्ट करने के लिए कि आप किस का उपयोग करना चाहते हैं, आप एक सेटर विधि या विभिन्न रचनाकारों का उपयोग कर सकते हैं। मुझे अभी भी वसंत की आवश्यकता नहीं दिख रही है। – fred

+0

http://stackoverflow.com/questions/871405/why-do-i-need-an-ioc-container-as-opposed-to-straightforward-di-code –

+1

वसंत ऐसा नहीं करता है कि आप स्वयं नहीं कर सकते , यह बस इतना है कि यदि आप वसंत करते हैं तो यह कम काम है। – milan

1

इम कि समस्या क्या है के रूप में नुकसान में,

समस्या dinamically रनटाइम पर या विन्यास फाइल के माध्यम से कार्यान्वयन स्वैप करने के लिए कैसे मूल रूप से है।

क्यों स्प्रिंग्स को निर्दिष्ट क्या इंटरफ़ेस के कार्यान्वयन एक एक्सएमएल फ़ाइल के अंदर उपयोग करने के लिए लगाने का समाधान बस कोड का एक लाइन होने की तुलना में बेहतर सही इंटरफ़ेस

यह क्योंकि बेहतर है का दृष्टांत है एक्सएमएल फ़ाइलों को पूरे ऐप को पुन: निर्माण और पुन: नियोजित किए बिना tweaked किया जा सकता है।

यह वहाँ बाहर डि पर सबसे अच्छा लेख में से एक है, तो आप इसे पर एक नज़र लेने के लिए चाहते हो सकता है: वर्ग एक वर्ग बी का उपयोग करता
http://martinfowler.com/articles/injection.html

+0

वह पूछ रहा है कि 'निर्भरता इंजेक्शन' क्या है। एनोटेशन का उपयोग करके आप एक्सएमएल के बिना डीआई का उपयोग कर सकते हैं। –

+0

क्षमा करें, मैं जवाब संपादित कर रहा था। –

+0

और मुख्य बिंदु रनटाइम पर कार्यान्वयन स्वैप नहीं करना है। बीटीडब्ल्यू, स्प्रिंग स्टार्टअप समय पर एक बार और सभी के लिए सभी निर्भरताओं को हल करता है। –

1

निर्भरता इंजेक्शन द्वारा हल की गई मुख्य समस्या यूनिट-परीक्षण है। मान लें कि आपके पास एक DoorOpeningService है जो परमाणु पर निर्भर करता है। DoorOpeningService को यूनिट-टेस्ट करने के लिए, आपको एक परमाणु संयंत्र होना चाहिए (जो कि खुले दरवाजों का परीक्षण करने के लिए बस महंगा और कठिन है)।

DoorOpeningService का कोड निम्नलिखित की तरह है:

public class DoorOpeningServiceImpl implements DoorOpeningService { 

    private NuclearPlant plant; 

    public DoorOpeningServiceImpl() { 
     this.plant = SomeNamingService.lookup("nuclearPlant"); 
    } 

    public void openDoors() { 
     int electricity = plant.getSomeElectricity(); 
     ... 
    } 
} 

DoorOpeningService इकाई परीक्षण करने के लिए बहुत कठिन है।

निर्भरता इंजेक्शन परमाणु संयंत्र को DoorOpeningService को देने की अनुमति देता है। इसलिए, एक वास्तविक परमाणु संयंत्र की आवश्यकता के बजाय, आप इसे एक नकली दे सकते हैं, जो हमेशा सभी वास्तविक परमाणु संयंत्र बुनियादी ढांचे की आवश्यकता के बिना कुछ बिजली देता है।और DoorOpeningService इस प्रकार परीक्षण करने के लिए और अधिक आसान है:

public class DoorOpeningServiceImpl implements DoorOpeningService { 

    private NuclearPlant plant; 

    // The plant is injected by constructor injection 
    public DoorOpeningServiceImpl(NuclearPlant plant) { 
     this.plant = plant; 
    } 

    public void openDoors() { 
     int electricity = plant.getSomeElectricity(); 
     ... 
    } 
} 

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

+0

वह पूछ रहा है कि उसे स्प्रिंग का उपयोग क्यों करना चाहिए, जब वह निम्न कार्य कर सकता है: नया DoorOpeningServiceImpl (नया NuclerPlant())। –

+0

क्षमा करें, लेकिन मुझे नहीं लगता कि वसंत के साथ क्या करना है? यह बिल्कुल मेरा मुद्दा है, अगर dooropeningserviceimpl विभिन्न पौधों का उपयोग करने में सक्षम होना चाहिए, तो बस सेटर्स या कन्स्ट्रक्टर का उपयोग करें ताकि अन्य वर्गों को यह निर्दिष्ट किया जा सके कि dooropeningserviceimpl का कौन सा संयंत्र उपयोग करना चाहिए। वसंत की कोई ज़रूरत नहीं है? – fred

+0

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

1

निर्भरता इंजेक्शन का उपयोग कर के लाभ के लिए आता है तो आपको निम्न

Interface i; 
if (useA) { 
    i = new A(); 
} else if (useB) { 
    i = new B(); 
} else if (useC) { 
    i = new C(); 
} 
i.call(); 

आप Interface के कई अलग अलग प्रकार है जैसे कोड है और आप जब आप प्रोग्राम चलाते हैं क्योंकि आप डॉन का उपयोग करने के जो एक का चयन करने की जरूरत है जब ' जब आप प्रोग्राम लिखते हैं तो किसको उपयोग करना है। इसका मतलब यह है कि प्रोग्राम शुरू करते समय useA, useB और useC किसी भी तरह से पता लगाना आवश्यक है। एक सामान्य दृष्टिकोण यह है कि पहचान मूल्य या एक प्रॉपर्टी फ़ाइल जो लोड हो, इन मानों को सेट करना है।

इसके अलावा "वास्तव में कौन है करें" भाग को उदाहरण देना मुश्किल हो सकता है वेब अनुप्रयोग जो मुख्य रूप से बाहर से कॉल किए जाने वाले कोड होते हैं।

निर्भरता इंजेक्शन इस तरह formalizes:

@Injection Interface i; 
i.call(); 

स्प्रिंग, i स्वचालित रूप से प्रारंभ करता है ताकि आप झंडे या जहां एक मानक तरीके से, कारखाने लगाने के लिए के बारे में अपने कोड में चिंता करने की जरूरत नहीं है। वास्तविक कोड से ए, बी, सी को संभालने का यह अलगाव बहुत साफ कोड बनाने के लिए साबित हुआ है।


संपादित करें: जब यह सवाल मैं समझ गया कि प्रश्न वास्तव में है? "क्यों निर्भरता इंजेक्शन जब आप getters और setters साथ भी ऐसा ही कर सकते हैं का उपयोग करें" की समीक्षा।

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

+0

कोई भी आपके उदाहरण में दिखाए गए तरीके को क्यों कोड करेगा? यह कौन से सेटर्स के लिए हैं? बाहर से निर्दिष्ट करने के लिए सेटर्स और कन्स्ट्रक्टर का उपयोग करने के लिए इंटरफ़ेस कार्यान्वयन का उपयोग सामान्य कोड का उपयोग करके एक ही परिणाम उत्पन्न करता है? – fred

+0

@fred, यह एक सरल उत्तर था। यह एक कारखाने के लिए भी एक कॉल किया जा सकता है। _Somewhere_ आपको अनिवार्य रूप से उस कोड को ए, बी, और सी के बीच चुनना होगा। _you_ इसे कहां रखा जाए? –

+0

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

0

इम कि समस्या क्या है के रूप में नुकसान में, और क्यों स्प्रिंग्स समाधान का दृष्टांत बस कोड का एक लाइन होने से बेहतर है सही इंटरफ़ेस?

सबसे पहले, config एक ही लग रहा है (और एक ही स्थान पर पाया जा सकता है) क्या अपने अनुप्रयोग एक वेब अनुप्रयोग, डेस्कटॉप, आदि एक नाबालिग लाभ है यही कारण है की परवाह किए बिना, लेकिन मैं इसे मिल गया है एक परियोजना विरासत के दौरान आसान काम करते हैं।

दूसरा, आप अक्सर कॉन्फ़िगरेशन के किसी प्रकार का बाहरीकरण चाहते हैं - जैसे कि ऐप के पुनर्निर्माण के बिना बाहरी सेवाओं, टाइमआउट सीमा आदि में यूआरएल बदलना, जिसका मतलब है कि आप बिना किसी कॉन्फ़िगरेशन फ़ाइल के साथ हवा में जा रहे हैं।और ऐसा ही होता है कि स्प्रिंग का कॉन्फ़िगरेशन प्रारूप बहुत शक्तिशाली है - हार्डकोड सामग्री में सक्षम होने के अलावा (जैसे कि "बीन fooDao यह डेटाबेस का उपयोग करके JpaFooDao का उदाहरण होना चाहिए"), आप refer to Java constants के साथ-साथ सिस्टम गुण (${propertyName} वाक्यविन्यास के साथ), perform JNDI lookups, add aspect wrappers जो उदाहरण के लिए make stuff transactional without coding, और अधिक कर सकते हैं। आप सभी स्वयं को बना सकते हैं, लेकिन काम की काफी मात्रा के बिना नहीं।

मैं एक्सएमएल से जितना ज्यादा नफरत करता हूं, लेकिन मुझे स्प्रिंग की एक्सएमएल कॉन्फ़िगरेशन को कभी भी परेशान नहीं किया गया है (कम से कम जब एनोटेशन के साथ ऑफलोड किया गया हो)।

संबंधित मुद्दे