समझ वसंत @Autowired उपयोग


309

मैं स्प्रिंग ऑटोज़र्ड एनोटेशन को समझने के लिए स्प्रिंग 3.0.x संदर्भ प्रलेखन पढ़ रहा हूं:

3.9.2 @Autowired और @ इंजेक्ट

मैं नीचे के उदाहरणों को समझने में सक्षम नहीं हूं। क्या हमें काम करने के लिए XML में कुछ करने की आवश्यकता है?

उदाहरण 1

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Autowired
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...
}

उदाहरण २

public class MovieRecommender {

    private MovieCatalog movieCatalog;

    private CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public void prepare(MovieCatalog movieCatalog,
                    CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }

    // ...
}

एक ही इंटरफ़ेस को लागू करने और एक ही वर्ग का उपयोग करके दो वर्गों को कैसे ऑटो किया जा सकता है?

उदाहरण:

class Red implements Color
class Blue implements Color

class myMainClass{
    @Autowired 
    private Color color;

    draw(){
        color.design(); 
    } 
}

किस डिजाइन विधि को कहा जाएगा? मैं यह कैसे सुनिश्चित करूं कि रेड क्लास का डिज़ाइन तरीका कहा जाएगा और ब्लू नहीं?

जवाबों:


542

टी एल; डॉ

@Autowired एनोटेशन आपको XML फ़ाइल (या किसी अन्य तरीके) से अपने आप वायरिंग करने की आवश्यकता है और आपको केवल यह बताता है कि आपको कहां इंजेक्ट किया जाना चाहिए और आपके लिए क्या करना है।

पूरी व्याख्या

@Autowiredएनोटेशन आप क्या सुई की कहीं और विन्यास को छोड़ने के लिए अनुमति देता है और सिर्फ तुम्हारे लिए यह करता है। अपना पैकेज मानते हुए com.mycompany.moviesआपको यह टैग अपनी XML (एप्लिकेशन संदर्भ फ़ाइल) में लगाना होगा:

<context:component-scan base-package="com.mycompany.movies" />

यह टैग एक ऑटो-स्कैनिंग करेगा। प्रत्येक वर्ग को माना जाता है कि बीन बनना है, एक सही एनोटेशन के साथ एनोटेट किया जाता है जैसे @Component(सरल बीन के लिए) या @Controller(सर्वलेट कंट्रोल के लिए) या @Repository( DAOकक्षाओं के लिए) और ये कक्षाएं पैकेज के तहत कहीं हैं com.mycompany.movies, बसंत इन सभी को ढूंढेंगे और बनाएं हर एक के लिए एक सेम। यह कक्षाओं के 2 स्कैन में किया जाता है - पहली बार यह केवल उन कक्षाओं की खोज करता है जो एक बीन बनने की आवश्यकता होती है और उन इंजेक्शनों को मैप करते हैं जिन्हें यह करने की आवश्यकता होती है, और दूसरे स्कैन में यह बीन्स को इंजेक्ट करता है। बेशक, आप अपनी सेम को अधिक पारंपरिक XML फ़ाइल में या @Configuration क्लास (या तीनों के किसी भी संयोजन) के साथ परिभाषित कर सकते हैं ।

@Autowiredएनोटेशन स्प्रिंग बताता है जहां एक इंजेक्शन होने की जरूरत है। यदि आप इसे एक विधि पर रखते हैं, तो setMovieFinderयह समझता है (उपसर्ग set+ @Autowiredएनोटेशन द्वारा) कि एक बीन को इंजेक्ट करने की आवश्यकता है। दूसरे स्कैन में, स्प्रिंग एक प्रकार की फलियों की खोज करता है MovieFinder, और यदि वह इस तरह की बीन पाता है, तो वह इसे इस विधि में इंजेक्ट करता है। यदि यह दो ऐसे फलियां पाता है तो आपको ए Exception। इससे बचने के लिए Exception, आप @Qualifierएनोटेशन का उपयोग कर सकते हैं और यह बता सकते हैं कि दोनों बीन्स में से किसको निम्न तरीके से इंजेक्ट करना है:

@Qualifier("redBean")
class Red implements Color {
   // Class code here
}

@Qualifier("blueBean")
class Blue implements Color {
   // Class code here
}

या यदि आप अपने XML में सेम घोषित करना पसंद करते हैं, तो यह कुछ इस तरह दिखाई देगा:

<bean id="redBean" class="com.mycompany.movies.Red"/>

<bean id="blueBean" class="com.mycompany.movies.Blue"/>

में @Autowiredघोषणा, आप भी जोड़ने की जरूरत है @Qualifierजो दो रंग सेम के इंजेक्षन करने के लिए बताने के लिए:

@Autowired
@Qualifier("redBean")
public void setColor(Color color) {
  this.color = color;
}

यदि आप दो एनोटेशन (ए @Autowiredऔर @Qualifier) का उपयोग नहीं करना चाहते हैं, तो आप @Resourceइन दोनों को संयोजित करने के लिए उपयोग कर सकते हैं :

@Resource(name="redBean")
public void setColor(Color color) {
  this.color = color;
}

@Resource(आप इस जवाब पर पहली टिप्पणी में इसके बारे में कुछ अतिरिक्त डेटा पढ़ सकते हैं) आप दो एनोटेशन के उपयोग के पुर्जों और इसके बजाय आप केवल एक का उपयोग करें।

मैं अभी दो और टिप्पणियाँ जोड़ूंगा:

  1. अच्छा अभ्यास @Injectइसके बजाय उपयोग करना होगा @Autowiredक्योंकि यह स्प्रिंग-विशिष्ट नहीं है और मानक का हिस्सा हैJSR-330
  2. एक और अच्छा अभ्यास एक विधि के बजाय एक कंस्ट्रक्टर पर @Inject/ डाल दिया जाएगा @Autowired। यदि आप इसे एक कंस्ट्रक्टर पर रखते हैं, तो आप यह पुष्टि कर सकते हैं कि इंजेक्ट किए गए बीन्स शून्य नहीं हैं और जब आप एप्लिकेशन शुरू करने से बचने की कोशिश करते हैं और NullPointerExceptionजब आपको वास्तव में बीन का उपयोग करने की आवश्यकता होती है, तो तेजी से असफल हो जाते हैं ।

अपडेट : चित्र को पूरा करने के लिए, मैंने कक्षा के बारे में एक नया प्रश्न बनाया @Configuration


6
बस अपने भयानक उत्तर को पूरा करने के लिए: '@Resource' JSR-250 मानक का हिस्सा है और सरल इंजेक्शन के ऊपर और ऊपर अतिरिक्त शब्दार्थ है (जैसा कि आपने कहा है कि '@Autowired' स्प्रिंग से है, और '@Inject' हिस्सा है) JSR-330) :)
इग्नासियो रूबियो

यदि MovieFinderएक इंटरफ़ेस है, और हमारे पास MovieFinderImpl(सेम आईडी = मूवीफाइंडर) के लिए बीन है, तो स्प्रिंग इसे ऑटो टाइप या नाम से इंजेक्ट करेगा?
जसकी J

@ जॅस्की - यह इस बात पर निर्भर करता है कि आप उपयोग करते हैं या नहीं @Qualifier। यदि आप करते हैं - नाम से, यदि नहीं - प्रकार से। यदि MovieFinderआपके संदर्भ में केवल एक बीन प्रकार है तो बाय-टाइप काम करेगा । 1 से अधिक एक अपवाद को जन्म देगा।
अवी

@Avi, बहुत बढ़िया जवाब। लेकिन मुझे समझ में नहीं आता है कि उदाहरण 2 में विधि @Autowiredपर एनोटेशन कैसे काम करता है । यह तकनीकी रूप से लेकिन, यह एक सेटर नहीं है। prepareMovieRecommender
करण चड्ढा

@ केरनछाड़ - निर्माणकर्ताओं के @Autowiredलिए भी काम करता है। यह आवश्यक निर्भरता पाता है और उन्हें निर्माता को इंजेक्ट करता है।
एवी

21

उदाहरण में कुछ भी नहीं कहा गया है कि "समान इंटरफ़ेस को लागू करने वाली कक्षाएं"। MovieCatalogएक प्रकार है और CustomerPreferenceDaoएक अन्य प्रकार है। वसंत उन्हें आसानी से अलग बता सकता है।

स्प्रिंग 2.x में, सेम की वायरिंग ज्यादातर सेम आईडी या नामों के माध्यम से हुई। यह अभी भी स्प्रिंग 3.x द्वारा समर्थित है लेकिन अक्सर, आपके पास एक निश्चित प्रकार के साथ बीन का एक उदाहरण होगा - अधिकांश सेवाएं एकल हैं। उन लोगों के लिए नाम बनाना थकाऊ है। इसलिए स्प्रिंग ने "ऑटोवेयर बाय टाइप" का समर्थन करना शुरू कर दिया।

उदाहरण क्या दिखाते हैं विभिन्न तरीकों से आप सेम को खेतों, विधियों और निर्माणकर्ताओं में इंजेक्ट कर सकते हैं।

एक्सएमएल में पहले से ही सभी जानकारी शामिल है जो वसंत की जरूरत है क्योंकि आपको प्रत्येक बीन में पूरी तरह से योग्य वर्ग नाम निर्दिष्ट करना होगा। आपको इंटरफेस के साथ थोड़ा सावधान रहने की जरूरत है, हालांकि:

यह स्वत: निष्फल हो जाएगा:

 @Autowired
 public void prepare( Interface1 bean1, Interface1 bean2 ) { ... }

चूंकि जावा बाइट कोड में पैरामीटर नाम नहीं रखता है, इसलिए स्प्रिंग अब दो सेम के बीच अंतर नहीं कर सकता है। उपयोग करने के लिए ठीक है @Qualifier:

 @Autowired
 public void prepare( @Qualifier("bean1") Interface1 bean1,
     @Qualifier("bean2")  Interface1 bean2 ) { ... }

@AaronDigulla यह अच्छा था। हालाँकि मैं जानना चाहता हूं कि आप फ़ंक्शन को कैसे कॉल करते हैं prepare, इस फ़ंक्शन को कॉल करने के लिए कौन से पैरामीटर का उपयोग किया जाएगा?
गुयेन क्वांग अन्ह

@NguyenQuangAnh मैं विधि नहीं कह रहा हूं, बीन बनने पर स्प्रिंग ऐसा करेगा। यह ठीक तब होता है जब @Autowiredखेतों में इंजेक्शन लगाया जाता है। वसंत तब देखेगा कि मापदंडों की आवश्यकता है और यह मापदंडों को खोजने के लिए फ़ील्ड इंजेक्शन के लिए उपयोग किए जाने वाले समान नियमों का उपयोग करेगा।
आरोन दिगुल्ला

5

हां, आप अपनी सेम (यानी, कक्षाएं) को परिभाषित करने के लिए स्प्रिंग सर्वलेट संदर्भ xml फ़ाइल को कॉन्फ़िगर कर सकते हैं, ताकि यह आपके लिए स्वचालित इंजेक्शन कर सके। हालाँकि, ध्यान दें, कि आपको स्प्रिंग अप और रनिंग करने के लिए अन्य कॉन्फ़िगरेशन करने होंगे और ऐसा करने का सबसे अच्छा तरीका है, एक ट्यूटोरियल ग्राउंड का पालन करना।

एक बार जब आप अपने स्प्रिंग को कॉन्फ़िगर कर लेते हैं, तो आप अपने स्प्रिंग सर्वलेट संदर्भ xml फ़ाइल में उदाहरण 1 के लिए ऊपर काम कर सकते हैं (कृपया com.movies के पैकेज का नाम बदलें जो कि सही पैकेज का नाम है और यदि यह एक 3 पार्टी है क्लास, फिर सुनिश्चित करें कि उपयुक्त जार फ़ाइल क्लासपाथ पर है):

<beans:bean id="movieFinder" class="com.movies.MovieFinder" />

या यदि मूवीफ़ाइंडर वर्ग के पास एक आदिम मूल्य के साथ एक निर्माता है, तो आप इस तरह से कुछ कर सकते हैं,

<beans:bean id="movieFinder" class="com.movies.MovieFinder" >
    <beans:constructor-arg value="100" />
</beans:bean>

या यदि मूवीफ़ाइंडर वर्ग को एक निर्माता से दूसरे वर्ग की उम्मीद है, तो आप ऐसा कुछ कर सकते हैं,

<beans:bean id="movieFinder" class="com.movies.MovieFinder" >
    <beans:constructor-arg ref="otherBeanRef" />
</beans:bean>

... जहाँ ' otherBeanRef ' एक और बीन है जिसमें अपेक्षित वर्ग का संदर्भ है।


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