2017-11-03 5 views
8

स्प्रिंग 3.X.X का उपयोग कर रहा है। मेरे पास @ प्राइमरी के साथ एनोटेटेड 2 सेवाएं हैं और मैंने एक और कॉन्फ़िगरेशन क्लास बनाया है जहां मैं सेवाओं में से एक के "अनुकूलित" संस्करण का उपयोग करना चाहता हूं।स्प्रिंग ओवरराइड बीन कॉन्फ़िगरेशन इसकी "प्राथमिक" एक

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

मैं यह आसान कोड के साथ व्याख्या करने के लिए मिल जाए, यहाँ एक उदाहरण है:

इंटरफ़ेस फू:

@Primary 
@Service("FooImpl") 
public class FooImpl implements Foo { 

    private String message = "fooDefaultMessage"; 

    @Override 
    public String getMessage() { 
     return message; 
    } 

    public void setMessage(String message) { 
     this.message = message; 
    } 
} 

बार इंटरफ़ेस:

public interface Foo { 
    String getMessage(); 
} 

एक डिफ़ॉल्ट संदेश hardcoded साथ प्राथमिक कार्यान्वयन:

public interface Bar { 

    void doBar(); 
} 
,210

बार डिफ़ॉल्ट कार्यान्वयन:

@Primary 
@Service("BarImpl") 
public class BarImpl implements Bar { 

    private Foo foo; 

    @Override 
    public void doBar() { 
     System.out.println(foo.getMessage()); 
    } 

    public Foo getFoo() { 
     return foo; 
    } 

    @Autowired 
    public void setFoo(Foo foo) { 
     this.foo = foo; 
    } 
} 

अब तक तो अच्छा, मुझे लगता है मैं सब कुछ प्राप्त की उम्मीद के रूप में एक बार सम्मिलित करें करना चाहते हैं।

@Configuration 
public class BeanConfiguration { 

    @Bean 
    @Qualifier("readOnlyFoo") 
    Foo readOnlyFoo() { 
     FooImpl foo = new FooImpl(); 
     foo.setMessage("a read only message"); 
     return foo; 
    } 

    @Bean 
    @Qualifier("readOnlyBar") 
    Bar readOnlyBar() { 
     BarImpl bar = new BarImpl(); 
     bar.setFoo(readOnlyFoo()); 
     return bar; 
    } 
} 

जब मैं एक readOnlyBar इंजेक्षन करना चाहते हैं मैं डिफ़ॉल्ट फू के बजाय यहां सेट एक हो रही है: बात मैं निम्नलिखित के साथ एक विन्यास है।

private Bar readOnlyBar; 

@Autowired 
@Qualifier("readOnlyBar") 
public void setReadOnlyBar(Bar readOnlyBar) { 
    this.readOnlyBar = readOnlyBar; 
} 

... 
readOnlyBar.doBar(); 

"fooDefaultMessage" के साथ फू बीन है। ऐसा क्यों है? मैं कैसे सुनिश्चित कर सकता हूं कि स्प्रिंग @ कॉन्फ़िगरेशन पर सेट बीन का उपयोग करता है?

अग्रिम धन्यवाद,

संपादित करें: नोट है कि एक ही है, तो बजाय @Configuration कक्षा में केवल पढ़ने के लिए() विधि को बुलाने की क्या होता है जब आप एक @Qualified तर्क गुजरती हैं। यानी .:

@Configuration 
public class BeanConfiguration { 

    @Bean 
    @Qualifier("readOnlyFoo") 
    Foo readOnlyFoo() { 
     FooImpl foo = new FooImpl(); 
     foo.setMessage("a read only message"); 
     return foo; 
    } 

    @Bean 
    @Qualifier("readOnlyBar") 
    Bar readOnlyBar(@Qualifier("readOnlyFoo") Foo readOnlyFoo) { 
     BarImpl bar = new BarImpl(); 
     bar.setFoo(readOnlyFoo); 
     return bar; 
    } 
} 

, तो इसके बजाय मैं निर्माता निर्भरता इंजेक्शन सब कुछ का उपयोग कर की कोशिश काम करता है के रूप में मैं चाहता हूँ/उम्मीद लेकिन दुर्भाग्य से मुझे लगता है कि उपयोग नहीं कर सकते।

+0

आप इस के लिए प्रोफ़ाइल का उपयोग नहीं कर सकते? –

+0

यह सुनिश्चित नहीं है कि प्रोफाइल यहां कैसे मदद करेंगे। हां, मेरे पास डिफ़ॉल्ट कार्यान्वयन का उपयोग करके एक प्रोफ़ाइल हो सकती है और दूसरा जो केवल पढ़ने के लिए इंगित करता है। प्रश्न यह है कि डिफ़ॉल्ट रूप से केवल एक त्वरित (केवल पढ़ने के लिए) बीन्स को पढ़ने के लिए सेट करें। – void

उत्तर

2

आप एक उदाहरण चर पर @Autowired का उपयोग नहीं कर सकते हैं और यह सेट किया है कि @Bean विधि जैसा आपने किया था। वसंत जीवन चक्र का एक हिस्सा इस तरह से चला जाता है

बीन परिभाषाओं को स्कैन कर => बीन उदाहरणों बनाई => पोस्ट प्रोसेसर => .....

अपने उदाहरण में,

@Bean 
@Qualifier("readOnlyBar") 
Bar readOnlyBar() { 
    BarImpl bar = new BarImpl(); 
    bar.setFoo(readOnlyFoo()); 
    return bar; 
} 

readOnlyBar सेम हो जाता है कहा जाता है बनाया गया और क्योंकि readOnlyFoo() इस विधि के भीतर से कहा जाता है, readOnlyFoo बीन भी तत्काल हो जाता है। इस बिंदु तक, readOnlyBar में इसके उदाहरण चर में readOnlyFoo है। एक बार बीन तत्काल हो जाने पर, AutowiredAnnotationBeanPostProcessor को कॉल किया जाता है जिसे उदाहरण के चर या विधियों पर @Autowired एनोटेशन के लिए बीन (BarImpl इस मामले में) स्कैन किया जाता है।यह उन्हें पाता है और क्षेत्र इंजेक्शन या सेटर इंजेक्शन (जहां @Autowired एनोटेशन मौजूद है) का उपयोग करते हुए अनुकूल चरों में सेम इंजेक्षन करने की कोशिश करता। इस मामले में हमारे पास @Autowired सेटर है और @Qualifier एनोटेशन निर्दिष्ट नहीं किया है, वसंत @Primary बीन इंजेक्ट करता है जो defaultFooMessage बीन है।

AFAIK, वहाँ वसंत में कॉन्फ़िगर करने के लिए @Bean तरीकों Autowiring पर वरीयता दी करने के लिए कोई सीधा रास्ता है।

@Bean तरीकों के साथ सभी सेम instantiating इस मुद्दे को ठीक होगा। बीन और सफल होने वाला:

2

आमतौर पर यह दो एनोटेशन के बजाय @Bean ("beanName") का उपयोग करने के लिए बेहतर है। और मुझे यकीन नहीं है कि क्वालिफायर बीन्स नामकरण के लिए काम करता है। वैसे भी आपको एक शैली में कोड लिखना चाहिए। इसलिए यदि आप @ सेवा एनोटेशन में मूल्य विशेषता का उपयोग करते हैं तो आपको @ बीन एनोटेशन में मूल्य विशेषता का उपयोग करना चाहिए।

क्षेत्र @Autowired List<Foo> allFoos बनाएँ और डिबग मोड में उसे देखें। आप सभी फू बीन्स देखेंगे ताकि आप उनके नाम देख सकें।

2

जैसा कि @Yaswanth ने अपने उत्तर में बताया, समस्या यह थी कि foo संपत्ति बीन के निर्माण के बाद होने वाली संपत्ति इंजेक्शन द्वारा अधिलेखित की गई थी।

संपत्ति इंजेक्शन के बजाय BarImpl के लिए कन्स्ट्रक्टर इंजेक्शन का उपयोग करने के लिए एक तरीका है। यही कारण है कि अपने कोड नज़र होगा की तरह ...

@Primary @Service("BarImpl") 
class BarImpl implements Bar 
{ 
    private Foo foo; 

    @Autowired 
    public BarImpl(Foo foo) { 
     this.foo = foo; 
    } 
} 

और आपके विन्यास होगा ...

@Configuration 
class BeanConfiguration 
{ 
    @Bean @Qualifier("readOnlyFoo") 
    Foo readOnlyFoo() { 
     FooImpl foo = new FooImpl(); 
     foo.setMessage("a read only message"); 
     return foo; 
    } 

    @Bean @Qualifier("readOnlyBar") 
    Bar readOnlyBar(@Qualifier("readOnlyFoo") Foo readOnlyFoo) { 
     return new BarImpl(readOnlyFoo); 
    } 
} 

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

अपने भविष्य के प्रयासों के साथ शुभकामनाएँ!

+0

हालांकि मुझे यह पता था, क्योंकि यह प्रश्न में लिखा गया है, यह मेरी आवश्यक चीज़ों का सबसे नज़दीकी उत्तर है और बक्षीस खत्म होने वाला है, इसलिए मैंने इस जवाब को बक्षीस प्राप्त करने के लिए चुना है। – void

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