2013-05-27 10 views
8

मैं वसंत फ्रेमवर्क के लिए काफी नया हूं और मुझे जावा कॉन्फ़िगर किए गए एप्लिकेशन के साथ संयोजन में @Required एनोटेशन को समझने में समस्याएं आई हैं।JavaConfig के साथ @Required एनोटेशन कैसे काम करता है?

यहां एक उदाहरण है।

कॉन्फ़िग फ़ाइल

@Configuration 
public class AppConfig { 
    @Bean 
    public Movie movieA() { 
     return new Movie(); 
    } 

    @Bean 
    public MovieHolder holder() { 
     return new MovieHolder(); 
    } 
} 

MovieHolder.java

public class MovieHolder { 

    private Movie movie; 

    public Movie getMovie() { 
     return movie; 
    } 

    @Required 
    public void setMovie(Movie movie) { 
     this.movie = movie; 
    } 
} 

प्रसंग प्रारंभ

ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); 
MovieHolder holder = (MovieHolder) context.getBean("holder"); 
System.out.println("movie: " + holder.getMovie()); 

जहां तक मैं @Required एनोटेशन के दस्तावेज़ीकरण को समझ गया, वहां अपवाद बढ़ाना चाहिए, क्योंकि फिल्म सीधे या ऑटोवॉयरिंग द्वारा सेट नहीं की जाती है। इसके बजाय उत्पादन movie: null है।

मैं क्या गलत कर रहा हूं? या यह @Required एनोटेशन का सही उपयोग नहीं है?

उत्तर

8

बीन्स में आवश्यक गुणों को स्थापित करना जो आप तुरंत कर रहे हैं वह आपकी ज़िम्मेदारी है। BeanPostProcessor जो @Configuration के साथ एनोटेटेड कक्षाओं में बीन-परिभाषाओं को संसाधित करता है उसे ConfigurationClassPostProcessor कहा जाता है। BeanPostProcessor जो आपके @Required एनोटेशन डिफ़ॉल्ट को RequiredAnnotationBeanPostProcessor पर संसाधित करता है, जो आपके कॉन्फ़िगरेशन में context:annotation-config और context:component-scan का उपयोग करते समय डिफ़ॉल्ट रूप से पंजीकृत होता है। यदि आप इन दो टैग का उपयोग नहीं कर रहे हैं, तो आप RequiredAnnotationBeanPostProcessor को bean के रूप में भी पंजीकृत कर सकते हैं।

अब, RequiredAnnotationBeanPostProcessor के डिफ़ॉल्ट कार्यान्वयन में boolean shouldSkip(..) नामक एक विधि है जो SKIP_REQUIRED_CHECK_ATTRIBUTE नामक बूलियन विशेषता के लिए जांच करता है। RequiredAnnotationBeanPostProcessor द्वारा पोस्ट-प्रोसेसिंग के दौरान प्रत्येक बीन के लिए इस विशेषता का मान चेक किया गया है। यदि यह false देता है, तो @Required बाधा लागू होती है, अन्यथा यह नहीं है।

अब, ConfigurationClassPostProcessortrue को इस विशेषता का मान सेट जबकि @Configuration वर्गों (मैं कारण के लिए लगता है से सेम परिभाषाओं बनाने कि अगर आप एक सेम, परिभाषित कर रहे हैं आप यह सुनिश्चित करना चाहिए यह है कि आवश्यक गुण)। इसलिए, @Required ऐसे बीन्स के लिए लागू नहीं है।

एक तरफ के रूप में, आप सोच सकते हैं कि यह SKIP_REQUIRED_CHECK_ATTRIBUTE विशेषता कहां से आई है और यह कहां सेट है: यह BeanDefinition के उदाहरणों पर सेट है जिसका उपयोग आंतरिक रूप से बीन निर्माण और पोस्ट-प्रोसेसिंग के लिए किया जाता है।

तुम सच में @Required बाधाओं लागू करना चाहते हैं, तो आप, RequiredAnnotationBeanPostProcessor ओवरराइड boolean shouldSkip(..) विधि ओवरराइड और इस वर्ग के रजिस्टर डिफ़ॉल्ट RequiredAnnotationBeanPostProcessor के बजाय करना होगा।और जैसा कि RequiredAnnotationBeanPostProcessor के लिए दस्तावेज़ कहते हैं: ": एनोटेशन-config संदर्भ" और "संदर्भ: घटक स्कैन" एक्सएमएल टैग

एक डिफ़ॉल्ट RequiredAnnotationBeanPostProcessor द्वारा पंजीकृत किया जाएगा। यदि आप एक कस्टम RequiredAnotationBeanPostProcessor बीन परिभाषा निर्दिष्ट करने का इरादा रखते हैं तो डिफ़ॉल्ट एनोटेशन कॉन्फ़िगरेशन को हटाएं या बंद करें।

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

इसके अलावा, मेरी राय में, तब तक आपकी RequiredAnnotationBeanPostProcessor उपयोग करने के लिए मुसीबत का एक बहुत माध्यम से जा रहा है, तो निम्न प्रलेखन के रूप में में ज्यादा नहीं है का कहना है:

कृपया ध्यान दें कि एक 'init' पद्धति अभी भी हो सकता है लागू करने की आवश्यकता है (और अभी भी वांछनीय हो सकता है), क्योंकि यह वर्ग जो भी करता है वह यह है कि एक 'आवश्यक' संपत्ति वास्तव में मूल्य के साथ कॉन्फ़िगर की गई है। यह किसी और चीज की जांच नहीं करता है ... विशेष रूप से, यह जांच नहीं करता है कि कॉन्फ़िगर किया गया मान शून्य नहीं है।

तो, संक्षेप में प्रस्तुत करने के लिए:@Required डिफ़ॉल्ट रूप से @Configuration वर्गों के साथ काम नहीं करता। यदि आपको यह सुनिश्चित करने की ज़रूरत है कि आपकी सभी संपत्तियां सेट की गई हैं, तो आप @Bean विधियों में बीन बनाते समय भी इसे स्वयं कर सकते हैं (कुछ init विधि को कॉल करके ऐसी मान्यताओं को निष्पादित करते हैं, या केवल आवश्यक गुणों की आपूर्ति करते हैं)। और यदि आप वास्तव में को @Required एनोटेशन कार्य करने की आवश्यकता है, तो आपको RequiredAnnotationBeanPostProcessor के अपने कार्यान्वयन का उपयोग करने की आवश्यकता होगी, इसे वसंत संदर्भ में एक बीन के रूप में पंजीकृत करें और context:annotation-config के लाभों को छोड़ दें।

+0

अच्छा, आपके समाधान के लिए धन्यवाद, मैं इसे आज़मा दूंगा। लेकिन मुझे समझ में नहीं आता कि यह इतना जटिल क्यों है?जावा में परिभाषित विन्यासों का उपयोग करते समय '@ आवश्यक'-एनोटेशन का उपयोग न करने के कोई कारण हैं? –

+0

यदि आपको _really need_ की आवश्यकता है तो इसका उपयोग करें। इसके लिए चेतावनी हैं ('संदर्भ: एनोटेशन-कॉन्फ़िगरेशन' के लाभ खोना) और वैसे भी इसका उपयोग करने के लिए बहुत अधिक लाभ नहीं है। हालांकि यह बहुत जटिल नहीं है। आधिकारिक दस्तावेज़ीकरण बहुत मदद करता है, और यदि यह काम नहीं करता है, तो आप केवल स्रोत-कोड ब्राउज़ कर सकते हैं। आप शायद यह सुनिश्चित करने के लिए '@ आवश्यक' का उपयोग कर रहे हैं कि कुछ संपत्ति का वैध मान हो, और यह '@ आवश्यक' एनोटेशन नहीं कर रहा है। यदि आपको ऐसा करने की ज़रूरत है, तो बस इसे अपने '@ बीन' विधि में देखें या उत्तर में उल्लिखित 'initMethod' को लागू करें। –

+1

यह बात नहीं है, कि मुझे जरूरी '@ आवश्यक' टैग की आवश्यकता है। मैं अभी भी आश्चर्यचकित हूं, जावास्क्रिप्ट कॉन्फ़िगरेशन का उपयोग करते समय, इस टैग को हमेशा अनदेखा किया जाता है। 'ConfigurationClassBeanDefinitionReader' में मुझे निम्न पंक्ति मिली है: 'beanDef.setAttribute (आवश्यक एनीमेशन BeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE); यही कारण है कि आवश्यक चेक अलवा छोड़ दिया गया है। –

1

बस ओवरराइड shouldSkip() विधि के साथ एक @Bean RequiredAnnotationBeanPostProcessor घोषित करने की कोशिश।

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

जब आप किसी XML कॉन्फ़िगरेशन का उपयोग करते हैं, तो वसंत गुण सेट करने के लिए एक रैपर ऑब्जेक्ट बनाता है, इसलिए यह सभी कॉन्फ़िगर किए गए 'setXxx()' संचालन को ट्रैक कर सकता है।

निष्कर्ष: वहाँ जावा @Configuration कक्षाओं में बनाया सेम के लिए @Required एनोटेशन सक्षम करने के लिए कोई उचित तरीका है।
(मेरी राय में बहुत दुर्भाग्यपूर्ण विशेषता है, क्योंकि बीन क्लास लेखक और कक्षा उपयोगकर्ता अलग-अलग व्यक्ति हो सकते हैं)।

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