2017-03-10 10 views
5

में @autowired का उपयोग करें जैसा कि मुझे पता है, field injection अनुशंसित नहीं है। इसके बजाय constructor का उपयोग करना चाहिए।अमूर्त बेस क्लास

जो मैं यहां करने की कोशिश कर रहा हूं वह बेस क्लास के निर्माता में @Autowired का उपयोग कर रहा है, और इसे सभी उप-वर्गों के लिए सुलभ बना देता है। कुछ उप-वर्गों में, मुझे अपने रचनाकारों से @Autowired होने के लिए कुछ विशिष्ट बीन्स की भी आवश्यकता होती है। डेमो कोड निम्न प्रकार है:

बेस वर्ग:

public abstract class Base { 

    protected final MyDemoService myDemoService; 

    @Autowired 
    public Base(MyDemoService myDemoService) { 
     this.myDemoService = myDemoService; 
    } 
} 

पारंपरिक रूप से प्राप्त (उप) वर्ग:

public class Sub extends Base { 

    private final MySubService mySubService; 

    @Autowired 
    public Sub(MySubService mySubService) { 
     this.mySubService = mySubService; 
    } 
} 

यह मैं एक 'कोई डिफ़ॉल्ट निर्माता' त्रुटि दे देंगे।
यह प्रश्न के समान है: similar question and answer, लेकिन यह यहां काम नहीं करता है।


मैं थोड़ी देर के लिए इस में डुबकी लगाई है, मैं dependency injection के बारे में इस लेख पाया: further read

मैं सोच रहा हूँ Setter Injection मेरे सवाल के लिए एक सही तरीका है?

सेटर इंजेक्शन:

public abstract class Base { 

    protected MyDemoService myDemoService; 

    @Autowired 
    public void setMyDemoService(MyDemoService myDemoService) { 
     this.myDemoService = myDemoService; 
    } 
} 

मैं जावा स्प्रिंग बूट करने के लिए नए हूँ, और तुम लोगों से कुछ विशेषज्ञता सलाह प्राप्त करना चाहते हैं। किसी भी चर्चा की अत्यधिक सराहना की जाएगी!

+0

मुझे लगता है कि सेटर आपका सबसे अच्छा विकल्प है, क्योंकि कन्स्ट्रक्टर चीज एक भाषा विनिर्देश है और स्प्रिंग'श – Mehdi

+0

फील्ड इंजेक्शन की सिफारिश नहीं की जा रही है, एक सार्वभौमिक सत्य नहीं है। मैंने जो परियोजनाएं की हैं, हमने जानबूझकर इसका उपयोग करने का फैसला किया है ताकि बहुत सारे बॉयलरप्लेट कोड (कन्स्ट्रक्टर या सेटर्स जो केवल निर्भरताएं भरें) को बचा सकें जो रखरखाव या पठनीयता के लिए शून्य मान जोड़ता है। – john16384

+0

@Mehdi आपकी प्रतिक्रिया के लिए धन्यवाद। – Vigor

उत्तर

-2

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

फील्ड और सेटर इंजेक्शन हालांकि यह सही तरीके से करेगा।

मैं किसी भी मामले में फील्ड इंजेक्शन की सिफारिश करता हूं, क्योंकि यह कोड डुप्लिकेशन को कम करता है। तुलना करें:

class A { 
    @Autowired private Field field; 
} 

बनाम।

class A { 
    private final Field field; 

    /** plus mandatory javadocs */ 
    @Autowired 
    public A(Field field) { 
     this.field = field; 
    } 
} 

निर्माता इंजेक्शन उदाहरण में आप अपने आप को चार बार सिर्फ एक क्षेत्र जिस तरह से आप यह चाहते सेट प्राप्त करने के लिए ... भले ही मैं चीजों को अंतिम होने प्यार दोहराने, दोहराव इस तरह का सिर्फ यह मुश्किल कोड को बदलने के लिए बनाता है ।

1

फील्ड इंजेक्शन का उपयोग न करें, कन्स्ट्रक्टर इंजेक्शन का उपयोग सुपर कन्स्ट्रक्टर को उचित रूप से वापस कॉल करने के लिए करें।

कन्स्ट्रक्टर इंजेक्शन सुनिश्चित करता है कि आपकी ऑब्जेक्ट तत्कालता से पहले ठीक से आबादी हो, सेटर इंजेक्शन कोड को और अधिक बग प्रवण नहीं करता है (कोई अन्य नलपोइंटर बग नहीं है ....)

आप आप तो लिखने के रूप में यहाँ Why field injection is evil

स्प्रिंग 4 के रूप में वर्णित किया वैसे यदि आप केवल एक है परियोजना लंबोक का उपयोग लंबोक आप के लिए निर्माता कोड उत्पन्न करने देने के लिए है अतिरिक्त कोड के बारे में चिंतित हैं, तो आपकी कक्षा में एकल कन्स्ट्रक्टर आपको कन्स्ट्रक्टर पर @Autowired की आवश्यकता नहीं है।

1

आपके द्वारा प्रदान किया गया कोड संकलित नहीं होगा। जब तक आपकी बेस क्लास में आपके पास डिफॉल्ट कन्स्ट्रक्टर नहीं है, तो आपको बच्चे में super(MyDemoService) पर कॉल करना चाहिए।

पारंपरिक रूप से प्राप्त (उप) वर्ग:

public class Sub extends Base { 

    private final MySubService mySubService; 

    @Autowired 
    public Sub(MySubService mySubService, MyDemoService myDemoService){ 
     super(myDemoService); 
     this.mySubService = mySubService; 
    } 
} 

या, यदि MySubServiceMyDemoService

@Autowired 
public Sub(MySubService mySubService){ 
    super(mySubService); 
} 

के एक कार्यान्वयन जब तक अमूर्त वर्ग में अपने क्षेत्र MyDemoService myDemoService है के रूप में है protected आप इसका इस्तेमाल कर सकते हैं उपclasses में।

यदि आपके पास का एकाधिक कार्यान्वयन है, तो आपको @Qualifier का उपयोग करना होगा जैसा कि answer that you have mentioned में वर्णित है।

public Sub(@Qualifier("MySubService") MyDemoService mySubService){ 
    super(mySubService); 
} 
2

मैं @Configuration कक्षाओं का उपयोग करने का सुझाव दूंगा। इस तरह आप अपने व्यापार वर्गों से पूरी तरह से वसंत एनोटेशन बाहर निकालना कर सकते हैं:

public class Sub extends Base { 

    private final MySubService mySubService; 

    public Sub(MySubService mySubService, MyDemoService myDemoService){ 
     super(myDemoService); 
     this.mySubService = mySubService; 
    } 
} 

स्प्रिंग config:

@Configuration 
public class SubConfig{ 

    @Bean 
    public Sub sub(MySubService subService, MyDemoService demoService){ 
     return new Sub(subService, demoService); 
    } 
} 

विन्यास वर्गों के साथ, आप अब जादुई classpath स्कैनिंग पर भरोसा करते हैं, लेकिन वास्तव में मैन्युअल रूप से फिर से सेम का दृष्टांत। इस दृष्टिकोण में बहुत कम आश्चर्य है।

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