2012-05-23 19 views
14

क्या विधि कॉल में पैरामीटर इंजेक्ट करने के लिए सीडीआई का उपयोग करना संभव है? अपेक्षित व्यवहार क्षेत्र इंजेक्शन के समान होगा। पसंदीदा निर्माता देखा जाता है और उत्पाद का उपयोग किया जाता है। (कम भ्रामक sytax साथ)विधि पैरामीटर इंजेक्शन के लिए सीडीआई का उपयोग कैसे करें?

public void foo(@Inject Bar bar){ 
    //do stuff 
} 

या इस:

मुझे क्या करना चाहते हैं यह है

public void foo(){ 
    @Inject 
    Bar bar; 
    //do stuff 
} 

इस वाक्य रचना दोनों ही मामलों में गैर कानूनी है। क्या कोई विकल्प है? यदि नहीं - अगर यह संभव था तो किसी कारण से यह बुरा विचार होगा?

धन्यवाद

संपादित - मैं काफी स्पष्ट नहीं मेरी आवश्यकताओं बना दिया है सकते हैं - मैं विधि सीधे कॉल करने में सक्षम होना चाहते हैं, कंटेनर के लिए bar चर का प्रारंभ हो जाता है। जोर्न हॉर्स्टमैन और पर्सप्शन के जवाब से पता चलता है कि यह संभव नहीं है।

उत्तर

16

इंजेक्शन पॉइंट को बीन के लिए संसाधित किया जाता है जब इसे कंटेनर द्वारा तत्काल किया जाता है, जो विधि स्तर इंजेक्शन के लिए उपयोग मामलों की संख्या को सीमित करता है। विनिर्देश के वर्तमान संस्करण को पहचानता विधि इंजेक्शन के निम्नलिखित प्रकार:

प्रारंभकर्ता विधि इंजेक्शन

public class MyBean { 
    private Processor processor; 

    @Inject 
    public void setProcessor(final Processor processor) { 
     this.processor = processor; 
    } 
} 

जब MyBean का एक उदाहरण इंजेक्ट किया जाता है, प्रोसेसर उदाहरण भी इंजेक्ट किया जाएगा, के माध्यम से इसे सेटर विधि है ।

घटना ऑब्जर्वर तरीके

public class MyEventHandler { 
    public void processSomeEvent(@Observes final SomeEvent event) { 
    } 
} 

घटना उदाहरण सीधे घटना प्रबंधन विधि में इंजेक्ट किया जाता है (हालांकि, @Inject टिप्पणी के साथ नहीं)

निर्माता तरीके

public class ProcessorFactory { 
    @Produces public Processor getProcessor(@Inject final Gateway gateway) { 
     // ... 
    } 
} 

उत्पादक विधियों के पैरामीटर स्वचालित रूप से इंजेक्ट करते हैं ईडी।

+0

धन्यवाद, धारणा। पहला वाक्य मेरे सपनों को बर्बाद करने के लिए पर्याप्त था :) "जब इसे तत्काल किया जाता है"। जो मुझे दिमाग में था, उसे एक निर्माता विधि की तरह काम करना चाहिए। मुझे लगता है कि मेरा उपयोग मामला विशेषज्ञ समूह द्वारा नहीं किया गया था। – kostja

+0

हां, दुर्भाग्यवश विनिर्देश यह नहीं है कि विधि आविष्कार बीन लाइफसाइक्ल प्रबंधन का हिस्सा हों। तो, विधि को सीधे कॉल करना * नहीं * इंजेक्शन का आह्वान करेगा (यह ऑब्जेक्ट पर सीधे 'नया' कॉल करने जैसा ही होगा)। मैं आश्चर्यचकित नहीं होगा हालांकि विधि इंजेक्शन इसे spec के अगले संस्करण में बनाता है। – Perception

5

सीडीआई की उस विशेषता को "प्रारंभकर्ता विधि" कहा जाता है। वाक्यविन्यास आपके कोड से भिन्न है जिसमें पूरी विधि @Inject के साथ एनोटेट की गई है, विधि पैरामीटर को विशिष्ट बीन का चयन करने के लिए क्वालीफायर द्वारा एनोटेट किया जा सकता है। JSR 299 का सेक्शन 3.9 निम्नलिखित उदाहरण दिखाता है, @Selected क्वालीफायर होने के साथ ही छोड़ा जा सकता है यदि केवल एक बीन कार्यान्वयन हो।

@Inject 
void setProduct(@Selected Product product) { 
    this.product = product; 
} 

कृपया ध्यान दें कि

आवेदन प्रारंभकर्ता तरीकों सीधे फोन कर सकते हैं, लेकिन तब कोई पैरामीटर कंटेनर द्वारा विधि को दे दिया जाएगा।

+0

धन्यवाद, जोर्न, मैंने इस स्पेक भाग को पढ़ा। आपके नोट में मामला सटीक है जो मैं करना चाहता हूं - विधि को सीधे कॉल करें और कंटेनर एक बीन उदाहरण प्रदान करें। क्या इसके लिए सीडीआई में कोई और संभावना है? – kostja

1

आप प्रासंगिक संदर्भ पाने के लिए अपनी पद्धति में BeanManager एपीआई का उपयोग कर सकते हैं, या अपने अंतिम लक्ष्य के आधार पर आप विधि के

Instance<Bar> 

बाहर इंजेक्षन और विधि में इसका इस्तेमाल कर सकते हैं।

+0

धन्यवाद, covener। यह जानकर अच्छा लगा कि यह सब के बाद किया जा सकता है, हालांकि "मैन्युअल"। मुझे लगता है कि ज्यादातर मामलों में एक स्पष्ट लॉकअप की अतिरिक्त डब्ल्यूटीएफ-क्षमता के लिए वारंट नहीं है, लेकिन मैं संभावना को ध्यान में रखूंगा। – kostja

7

यदि आप वास्तव में चाहते हैं कि विधि के पैरामीटर (जो कॉलर द्वारा प्रदान किया जाना चाहिए) के पैरामीटर के रूप में कुछ नहीं है, लेकिन विधि को कॉल करते समय प्रत्येक बार एक सीडीआई बीन का एक उचित प्रारंभिक उदाहरण, और पूरी तरह से निर्मित और इंजेक्शन है, तो, जाँच

javax.inject.Provider<T>

मूल रूप से, प्रथम श्रेणी के एक प्रदाता इंजेक्षन

@Inject Provider<YourBean> yourBeanProvider; 

तो, विधि में एक नया उदाहरण प्राप्त

YourBean bean = yourBeanProvider.get(); 

आशा इस मदद करता है :)

+1

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

4

यह सवाल आया था जब मैं मूल रूप से इस विषय पर एक खोज किया था, और मैं के बाद से सीखा है CDI 1.1 की रिहाई (JavaEE 7 कल्पना में शामिल है) के साथ कि, वास्तव में ऐसा करने का एक तरीका है जो ओपी चाहता था, आंशिक रूप से। तुम अब भी

public void foo(@Inject Bar bar){ 
    //do stuff 
} 

ऐसा नहीं कर सकते, लेकिन आप एक स्थानीय चर "इंजेक्षन" कर सकते हैं, हालांकि आप @Inject का उपयोग नहीं करते बल्कि प्रोग्राम के रूप में इस तरह के इंजेक्शन उदाहरण देखो:

public void foo() { 
    Instance<Bar> instance = CDI.current().select(Bar.class); 
    Bar bar = instance.get(); 
    CDI.current().destroy(instance); 
    // do stuff with bar here 
} 

ध्यान दें कि select() विधि वैकल्पिक रूप से कोई क्वालीफायर एनोटेशन लेता है जिसे आपको प्रदान करने की आवश्यकता हो सकती है। शुभकामनाएं java.lang.annotation.Annotation के उदाहरण प्राप्त करने के बावजूद। अपनी इच्छित व्यक्ति को ढूंढने के लिए अपने Instance<Bar> के माध्यम से फिर से शुरू करना आसान हो सकता है।

मुझे बताया गया है कि आपको ऊपर दिए गए Instance<Bar> को नष्ट करने की आवश्यकता है, और उपरोक्त कोड काम करने वाले अनुभव से सत्यापित कर सकते हैं; हालांकि, मैं कसम खाता हूं कि को इसे नष्ट करने के लिए की आवश्यकता है।

+0

यह ठीक काम करता है लेकिन यूनिट परीक्षणों में समस्याएं पैदा कर सकता है। –

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