क्यों स्प्रिंग के ApplicationContext.getBean को बुरा माना जाता है?


270

मैंने एक सामान्य स्प्रिंग प्रश्न पूछा: ऑटो-कास्ट स्प्रिंग बीन्स और कई लोगों का जवाब था कि स्प्रिंग का कॉलिंगApplicationContext.getBean() को जितना संभव हो उतना बचा जाना चाहिए। ऐसा क्यों है?

मुझे उन सेम तक पहुंच कैसे प्राप्त करनी चाहिए जिन्हें मैंने बनाने के लिए स्प्रिंग कॉन्फ़िगर किया था?

मैं एक गैर-वेब अनुप्रयोग में स्प्रिंग का उपयोग कर रहा हूं और LiorH द्वारा वर्णित एक साझा ApplicationContextवस्तु तक पहुंचने की योजना बनाई थी

संशोधन

मैं नीचे दिए गए उत्तर को स्वीकार करता हूं, लेकिन यहां मार्टिन फाउलर द्वारा एक वैकल्पिक रूप से लिया गया है, जो सेवा लोकेटर का उपयोग करके बनाम निर्भरता इंजेक्शन के गुणों पर चर्चा करता है (जो अनिवार्य रूप से एक लिपटे को कॉल करने के समान है।ApplicationContext.getBean() )।

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

जवाबों:


202

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

कॉलिंग ApplicationContext.getBean()कंट्रोल का उलटा नहीं है! हालांकि यह अभी भी बदलना आसान है कि दिए गए बीन नाम के लिए क्या लागू किया गया है, यह निर्भरता प्रदान करने के लिए वर्ग अब सीधे वसंत पर निर्भर करता है और इसे किसी अन्य तरीके से प्राप्त नहीं कर सकता है। आप केवल टेस्ट क्लास में अपना मॉक कार्यान्वयन नहीं कर सकते हैं और इसे स्वयं पास कर सकते हैं। यह मूल रूप से स्प्रिंग के उद्देश्य को एक निर्भरता इंजेक्शन कंटेनर के रूप में पराजित करता है।

हर जगह आप कहना चाहते हैं:

MyClass myClass = applicationContext.getBean("myClass");

आपको इसके बजाय, उदाहरण के लिए, एक विधि घोषित करनी चाहिए:

public void setMyClass(MyClass myClass) {
   this.myClass = myClass;
}

और फिर आपके विन्यास में:

<bean id="myClass" class="MyClass">...</bean>

<bean id="myOtherClass" class="MyOtherClass">
   <property name="myClass" ref="myClass"/>
</bean>

वसंत तब स्वचालित रूप से इंजेक्ट myClassकिया जाएगा myOtherClass

इस तरह से सब कुछ घोषित करें, और इसके मूल में सभी कुछ इस तरह हैं:

<bean id="myApplication" class="MyApplication">
   <property name="myCentralClass" ref="myCentralClass"/>
   <property name="myOtherCentralClass" ref="myOtherCentralClass"/>
</bean>

MyApplicationसबसे केंद्रीय वर्ग है, और आपके कार्यक्रम में हर दूसरी सेवा पर कम से कम अप्रत्यक्ष रूप से निर्भर करता है। बूटस्ट्रैपिंग करते समय, अपनी mainविधि में, आप कॉल कर सकते हैं applicationContext.getBean("myApplication")लेकिन आपको getBean()कहीं और कॉल करने की आवश्यकता नहीं है!


3
क्या इससे संबंधित कुछ भी है जो ऑब्जेक्ट बनाते समय सिर्फ एनोटेशन के साथ काम करता है new MyOtherClass()? मैं @Autowired के बारे में जानता हूं, लेकिन मैंने इसे कभी भी खेतों पर इस्तेमाल किया है और यह टूट जाता है new MyOtherClass()..
टिम

70
यह सच नहीं है कि ApplicationContext.getBean () IoC नहीं है। नीथेर ने अपने सभी वर्गों को बसंत द्वारा त्वरित होना अनिवार्य कर दिया है । यह अनुचित हठधर्मिता है। यदि ApplicationContext को स्वयं इंजेक्ट किया जाता है, तो यह पूरी तरह से ठीक है कि किसी सेम को तुरंत इस तरह से पूछा जाए - और इसके द्वारा बनाई जाने वाली बीन्स को शुरू में इंजेक्ट किए गए ApplicationContext के आधार पर अलग-अलग कार्यान्वयन हो सकते हैं। उदाहरण के लिए, मेरे पास एक ऐसा परिदृश्य है जहां मैं गतिशील रूप से एक सेम नाम के आधार पर नए सेम इंस्टेंस बनाता हूं जो संकलन समय पर अज्ञात है लेकिन मेरी स्प्रिंग.एक्सएमएल फ़ाइल में परिभाषित कार्यान्वयन में से एक से मेल खाता है।
एलेक्स वर्डेन

3
एलेक्स के साथ सहमत, मेरे पास एक ही मुद्दा है, जहां एक कारखाना वर्ग को केवल यह पता होगा कि उपयोगकर्ता बातचीत के माध्यम से रन टाइम पर उपयोग करने के लिए कौन सा बीन या कार्यान्वयन है, मुझे लगता है कि यह वह जगह है जहां संदर्भ इंटरफ़ेस आता है
बेन 12

3
@elbek: applicationContext.getBeanनिर्भरता इंजेक्शन नहीं है: यह सीधे फ्रेमवर्क तक पहुंच रहा है, इसे सेवा लोकेटर के रूप में उपयोग कर रहा है ।
कॉलिनड

6
@ हर्मन: मैं स्प्रिंग के बारे में नहीं जानता, क्योंकि मैंने लंबे समय में इसका इस्तेमाल नहीं किया है, लेकिन JSR-330 / Guice / Dagger में, आप हर बार जब आपको ज़रूरत होती है, कॉल के Provider<Foo>बजाय इंजेक्शन लगाकर ऐसा करते हैं नया उदाहरण। कंटेनर के लिए कोई संदर्भ नहीं है, और आप आसानी से परीक्षण के लिए बना सकते हैं । Fooprovider.get()Provider
कोलिनड

64

नियंत्रण के उलट (आईओसी) पर सेवा लोकेटर पसंद करने के कारण हैं:

  1. सेवा लोकेटर आपके कोड में अनुसरण करने के लिए अन्य लोगों के लिए बहुत आसान है। IoC 'जादू' है, लेकिन रखरखाव प्रोग्रामर को आपके जटिल स्प्रिंग कॉन्फ़िगरेशन और स्थानों के सभी असंख्य तरीकों को समझना होगा कि आपने अपनी वस्तुओं को कैसे निकाल दिया।

  2. IoC कॉन्फ़िगरेशन समस्याओं को डीबग करना के लिए भयानक है। अनुप्रयोगों के कुछ वर्गों में गलत होने पर आवेदन शुरू नहीं होगा और आपको डिबगर के साथ आगे बढ़ने का मौका नहीं मिल सकता है।

  3. IoC मुख्य रूप से XML आधारित है (एनोटेशन से चीजों में सुधार होता है लेकिन अभी भी बहुत सारे XML बाहर हैं)। इसका मतलब है कि डेवलपर्स आपके कार्यक्रम पर तब तक काम नहीं कर सकते हैं जब तक कि वे स्प्रिंग द्वारा परिभाषित सभी जादू टैग को नहीं जानते हैं। अब जावा को जानना बहुत अच्छा नहीं है। यह कम अनुभव वाले प्रोग्रामर को बाधा देता है (अर्थात। यह अधिक जटिल समाधान का उपयोग करने के लिए वास्तव में खराब डिजाइन है जब एक सरल समाधान, जैसे कि सेवा लोकेटर, समान आवश्यकताओं को पूरा करेगा)। साथ ही, XML समस्याओं के निदान के लिए समर्थन जावा समस्याओं के समर्थन की तुलना में बहुत कमजोर है।

  4. निर्भरता इंजेक्शन बड़े कार्यक्रमों के लिए अधिक अनुकूल है। अधिकांश समय अतिरिक्त जटिलता इसके लायक नहीं है।

  5. अक्सर वसंत का उपयोग उस स्थिति में किया जाता है जब आप "बाद में कार्यान्वयन को बदलना चाहते हैं"। स्प्रिंग आईओसी की जटिलता के बिना इसे प्राप्त करने के अन्य तरीके हैं।

  6. वेब अनुप्रयोगों (जावा ईई वॉर्स) के लिए स्प्रिंग संदर्भ प्रभावी रूप से संकलन समय पर बाध्य है (जब तक कि आप चाहते हैं कि ऑपरेटर विस्फोट के युद्ध में संदर्भ के आसपास ग्रब न करें)। आप स्प्रिंग उपयोग संपत्ति फ़ाइलों को बना सकते हैं, लेकिन सर्वलेट्स के साथ संपत्ति फ़ाइलों को पूर्व-निर्धारित स्थान पर होना चाहिए, जिसका अर्थ है कि आप एक ही बॉक्स पर एक ही समय के कई सर्वलेट्स को तैनात नहीं कर सकते हैं। आप सर्वलेट स्टार्टअप समय पर संपत्तियों को बदलने के लिए JNDI के साथ स्प्रिंग का उपयोग कर सकते हैं, लेकिन यदि आप JNDI का उपयोग व्यवस्थापक-परिवर्तनीय मापदंडों के लिए कर रहे हैं, तो स्प्रिंग की आवश्यकता कम हो जाती है (क्योंकि JNDI प्रभावी रूप से सेवा लोकेटर है)।

  7. स्प्रिंग के साथ आप प्रोग्राम को खो सकते हैं यदि स्प्रिंग आपके तरीकों को भेज रहा है। यह सुविधाजनक है और कई प्रकार के अनुप्रयोगों के लिए काम करता है, लेकिन सभी नहीं। जब आपको इनिशियलाइज़ेशन के दौरान कार्यों (थ्रेड्स इत्यादि) बनाने की आवश्यकता होती है, तो आपको प्रोग्राम फ्लो को नियंत्रित करने की आवश्यकता हो सकती है या ऐसे परिवर्तनीय संसाधनों की आवश्यकता होती है, जिनके बारे में स्प्रिंग को तब पता न चले जब सामग्री आपके WAR से जुड़ी थी।

लेन-देन प्रबंधन के लिए वसंत बहुत अच्छा है और इसके कुछ फायदे हैं। यह सिर्फ इतना है कि IoC कई स्थितियों में ओवर-इंजीनियरिंग हो सकता है और अनुरक्षकों के लिए अनुचित जटिलता का परिचय दे सकता है। पहले उपयोग न करने के तरीकों के बारे में सोचे बिना आईओसी का स्वचालित रूप से उपयोग न करें।


7
प्लस - आपका ServiceLocator हमेशा स्प्रिंग से IoC का उपयोग कर सकता है, अपने कोड को स्प्रिंग पर निर्भर होने से रोक सकता है, स्प्रिंग एनोटेशन के साथ लिट और अनिर्दिष्ट मैजिक। मैंने हाल ही में GoogleAppEngine पर कोड का एक गुच्छा पोर्ट किया है जहां स्प्रिंग समर्थित नहीं है। काश मैं पहली जगह में एक ServiceFactory के पीछे सभी IoC छिपा होता!
एलेक्स वर्डेन

IoC एक एनीमिक डोमेन मॉडल को प्रोत्साहित करता है, जिसे मैं तिरस्कृत करता हूं। इकाई सेम को अपनी सेवाओं को देखने का एक तरीका चाहिए ताकि वे अपने व्यवहार को लागू कर सकें। उस परत पर, आपको वास्तव में एक सेवा लोकेटर की आवश्यकता नहीं हो सकती है।
जोएल

4
Bizar। मैं एनोटेशन के साथ हर समय स्प्रिंग का उपयोग करता हूं। हालांकि वास्तव में एक निश्चित सीखने की अवस्था शामिल है, अब, मुझे रखरखाव में कोई समस्या नहीं है, डिबगिंग, स्पष्टता, पठनीयता .... मुझे लगता है कि आप चीजों को कैसे ढाँचा है।
लॉरेंस

25

यह सच है कि आवेदन-संदर्भ में वर्ग सहित। xml getBean का उपयोग करने की आवश्यकता से बचा जाता है। हालांकि, यहां तक ​​कि वास्तव में अनावश्यक है। यदि आप एक स्टैंडअलोन एप्लिकेशन लिख रहे हैं और आप अपने ड्राइवर वर्ग को एप्लिकेशन के संदर्भ में शामिल नहीं करना चाहते हैं। xml, तो आप स्प्रिंग कोड को ड्राइवर की निर्भरता के लिए निम्न कोड का उपयोग कर सकते हैं:

public class AutowireThisDriver {

    private MySpringBean mySpringBean;    

    public static void main(String[] args) {
       AutowireThisDriver atd = new AutowireThisDriver(); //get instance

       ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
                  "/WEB-INF/applicationContext.xml"); //get Spring context 

       //the magic: auto-wire the instance with all its dependencies:
       ctx.getAutowireCapableBeanFactory().autowireBeanProperties(atd,
                  AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);        

       // code that uses mySpringBean ...
       mySpringBean.doStuff() // no need to instantiate - thanks to Spring
    }

    public void setMySpringBean(MySpringBean bean) {
       this.mySpringBean = bean;    
    }
}

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


मैं @Autowiredएनोटेशन के साथ भी सफलतापूर्वक इस विधि का उपयोग करने में सक्षम था ।
blong

21

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

जितना आप कहेंगे ClassINeed classINeed = (ClassINeed)ApplicationContext.getBean("classINeed"); , उतना कम जादू आपको मिल रहा है। कम कोड लगभग हमेशा बेहतर होता है। यदि आपकी कक्षा को वास्तव में क्लासिन बीड की आवश्यकता है, तो आपने इसे सिर्फ तार क्यों नहीं दिया?

उस ने कहा, कुछ स्पष्ट रूप से पहली वस्तु बनाने की जरूरत है। गेटबीन () के माध्यम से बीन या दो प्राप्त करने की आपकी मुख्य विधि में कुछ भी गलत नहीं है, लेकिन आपको इससे बचना चाहिए क्योंकि जब भी आप इसका उपयोग कर रहे हैं, आप वास्तव में स्प्रिंग के जादू का उपयोग नहीं कर रहे हैं।


1
लेकिन ओपी "क्लासिनिड" नहीं कह रहा है, वह "बीननेमिन" कह रहा है - जो आईओसी कंटेनर को किसी भी तरीके से कॉन्फ़िगर किए गए किसी भी वर्ग पर एक उदाहरण बनाने की अनुमति देता है। शायद यह आईओसी की तुलना में "सेवा लोकेटर" पैटर्न की तरह है, लेकिन यह अभी भी ढीली युग्मन में परिणाम देता है।
एचडीवी

16

प्रेरणा कोड लिखना है जो स्प्रिंग पर स्पष्ट रूप से निर्भर नहीं करता है। इस तरह, यदि आप कंटेनरों को स्विच करना चुनते हैं, तो आपको किसी भी कोड को फिर से लिखना नहीं पड़ेगा।

कंटेनर के बारे में सोचो के रूप में कुछ अपने कोड के लिए अदृश्य है, जादुई रूप से अपनी आवश्यकताओं के लिए प्रदान किए जा रहे हैं, बिना पूछे।

निर्भरता इंजेक्शन "सेवा लोकेटर" पैटर्न का एक प्रतिरूप है। यदि आप नाम से निर्भरता देखने जा रहे हैं, तो आप DI कंटेनर से छुटकारा पा सकते हैं और JNDI जैसी किसी चीज़ का उपयोग कर सकते हैं।


11

का उपयोग करना @Autowiredया ApplicationContext.getBean()वास्तव में एक ही बात है। दोनों तरीकों से आपको बीन मिलता है जो आपके संदर्भ में कॉन्फ़िगर किया गया है और दोनों तरीकों से आपका कोड वसंत पर निर्भर करता है। केवल एक चीज जिसे आपको बचना चाहिए, वह है आपका ApplicationContext। ऐसा केवल एक बार करें! दूसरे शब्दों में, एक लाइन की तरह

ApplicationContext context = new ClassPathXmlApplicationContext("AppContext.xml");

केवल आपके आवेदन में एक बार उपयोग किया जाना चाहिए।


नहीं। कभी-कभी @Autowired या ApplicationContext.getBean () कुल विभिन्न सेम का उत्पादन कर सकता है। मुझे यकीन नहीं है कि यह कैसे हुआ, लेकिन मैं अभी इस मुद्दे से जूझ रहा हूं।
ऑलेक्ज़ेंडर_जेड

4

विचार यह है कि आप निर्भरता इंजेक्शन ( नियंत्रण का उलटा , या IoC) पर भरोसा करते हैं । यही है, आपके घटकों को उन घटकों के साथ कॉन्फ़िगर किया गया है जिनकी उन्हें आवश्यकता है। इन निर्भरताओं को इंजेक्टर (कंस्ट्रक्टर या सेटर के माध्यम से) इंजेक्ट किया जाता है - आप तब स्वयं नहीं मिलते हैं।

ApplicationContext.getBean()आपको अपने घटक के भीतर एक बीन का नाम स्पष्ट रूप से रखने की आवश्यकता है। इसके बजाय, आईओसी का उपयोग करके, आपका कॉन्फ़िगरेशन यह निर्धारित कर सकता है कि किस घटक का उपयोग किया जाएगा।

यह आपको अलग-अलग घटक कार्यान्वयन के साथ आसानी से अपने आवेदन को फिर से स्थापित करने की अनुमति देता है, या नकली वेरिएंट प्रदान करके वस्तुओं को सीधे रूप में परीक्षण करने के लिए कॉन्फ़िगर करता है (उदाहरण के लिए एक नकली डीएओ ताकि आप परीक्षण के दौरान डेटाबेस को हिट न करें)


4

अन्य लोगों ने सामान्य समस्या की ओर इशारा किया है (और मान्य उत्तर हैं), लेकिन मैं सिर्फ एक अतिरिक्त टिप्पणी की पेशकश करूंगा: ऐसा नहीं है कि आपको यह कभी नहीं करना चाहिए, बल्कि यह भी कि जितना संभव हो उतना कम करें।

आमतौर पर इसका मतलब है कि यह एक बार किया जाता है: बूटस्ट्रैपिंग के दौरान। और फिर यह "रूट" बीन तक पहुंचना है, जिसके माध्यम से अन्य निर्भरताएं हल हो सकती हैं। यह पुन: प्रयोज्य कोड हो सकता है, जैसे बेस सर्वलेट (यदि वेब एप्लिकेशन विकसित करना)।


4

वसंत परिसर में से एक युग्मन से बचना है । परिभाषित करें और इंटरफेस, DI, AOP का उपयोग करें और ApplicationContext.getBean () :-) का उपयोग करने से बचें


4

कारणों में से एक परीक्षण क्षमता है। कहो कि आपके पास यह वर्ग है:

interface HttpLoader {
    String load(String url);
}
interface StringOutput {
    void print(String txt);
}
@Component
class MyBean {
    @Autowired
    MyBean(HttpLoader loader, StringOutput out) {
        out.print(loader.load("http://stackoverflow.com"));
    }
}

आप इस बीन का परीक्षण कैसे कर सकते हैं? इस तरह:

class MyBeanTest {
    public void creatingMyBean_writesStackoverflowPageToOutput() {
        // setup
        String stackOverflowHtml = "dummy";
        StringBuilder result = new StringBuilder();

        // execution
        new MyBean(Collections.singletonMap("https://stackoverflow.com", stackOverflowHtml)::get, result::append);

        // evaluation
        assertEquals(result.toString(), stackOverflowHtml);
    }
}

आसान है, है ना?

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

ApplicationContext का उपयोग करते समय भी ऐसा करना संभव है। हालाँकि तब आपको मज़ाक करने की ज़रूरत है ApplicationContextजो एक बहुत बड़ा इंटरफ़ेस है। आपको या तो डमी कार्यान्वयन की आवश्यकता है या आप मॉकिटो जैसे मॉकिंग फ्रेमवर्क का उपयोग कर सकते हैं:

@Component
class MyBean {
    @Autowired
    MyBean(ApplicationContext context) {
        HttpLoader loader = context.getBean(HttpLoader.class);
        StringOutput out = context.getBean(StringOutput.class);

        out.print(loader.load("http://stackoverflow.com"));
    }
}
class MyBeanTest {
    public void creatingMyBean_writesStackoverflowPageToOutput() {
        // setup
        String stackOverflowHtml = "dummy";
        StringBuilder result = new StringBuilder();
        ApplicationContext context = Mockito.mock(ApplicationContext.class);
        Mockito.when(context.getBean(HttpLoader.class))
            .thenReturn(Collections.singletonMap("https://stackoverflow.com", stackOverflowHtml)::get);
        Mockito.when(context.getBean(StringOutput.class)).thenReturn(result::append);

        // execution
        new MyBean(context);

        // evaluation
        assertEquals(result.toString(), stackOverflowHtml);
    }
}

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

एकमात्र विकल्प जो वास्तव में एक समस्या है यह एक है:

@Component
class MyBean {
    @Autowired
    MyBean(StringOutput out) {
        out.print(new HttpLoader().load("http://stackoverflow.com"));
    }
}

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

इसलिए एक निष्कर्ष के रूप में मैं यह नहीं कहूंगा कि ApplicationContextसीधे उपयोग करना स्वचालित रूप से गलत है और इसे हर कीमत पर टाला जाना चाहिए। हालांकि अगर बेहतर विकल्प हैं (और ज्यादातर मामलों में हैं), तो बेहतर विकल्पों का उपयोग करें।


3

मैंने केवल दो स्थितियों को पाया है जहाँ getBean () की आवश्यकता थी:

दूसरों ने स्टैंडबोन प्रोग्राम के लिए "मुख्य" बीन लाने के लिए गेटबीन () में मुख्य () का उपयोग करने का उल्लेख किया है।

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


3

एक और समय है जब getBean का उपयोग करने से समझ में आता है। यदि आप पहले से मौजूद एक सिस्टम को पुन: कॉन्फ़िगर कर रहे हैं, जहां निर्भरता को स्पष्ट रूप से वसंत संदर्भ फ़ाइलों में नहीं कहा जाता है। आप GetBean पर कॉल करके प्रक्रिया शुरू कर सकते हैं, ताकि आपको इसे एक ही बार में वायर न करना पड़े। इस तरह से आप धीरे-धीरे अपने स्प्रिंग कॉन्फ़िगरेशन का निर्माण कर सकते हैं और समय के साथ प्रत्येक टुकड़े को रख सकते हैं और बिट्स को ठीक से पंक्तिबद्ध कर सकते हैं। GetBean में कॉल को अंततः बदल दिया जाएगा, लेकिन जैसा कि आप कोड की संरचना को समझते हैं, या इसके अभाव में है, आप अधिक से अधिक सेम तारों की प्रक्रिया शुरू कर सकते हैं और getBean के लिए कम और कम कॉल का उपयोग कर सकते हैं।


2

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


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