फ़ील्ड को एनोटेट किया गया @Autowired
है null
क्योंकि स्प्रिंग को MileageFeeCalculator
आपके द्वारा बनाई गई प्रतिलिपि के बारे में new
नहीं पता है और इसे ऑटो करना नहीं जानता था।
स्प्रिंग इनवर्टर ऑफ़ कंट्रोल (IoC) कंटेनर में तीन मुख्य तार्किक घटक होते हैं: एक रजिस्ट्री (जिसे ApplicationContext
घटकों के प्रकार (बीन्स) कहा जाता है ) जो अनुप्रयोग द्वारा उपयोग किए जाने के लिए उपलब्ध हैं, एक विन्यासकर्ता प्रणाली जो ऑब्जेक्ट की निर्भरता को मेल करके उन पर निर्भर करती है। संदर्भ में बीन्स के साथ निर्भरताएं, और एक निर्भरता सॉल्वर जो कई अलग-अलग बीन्स के कॉन्फ़िगरेशन को देख सकते हैं और निर्धारित कर सकते हैं कि उन्हें आवश्यक क्रम में कैसे त्वरित और कॉन्फ़िगर किया जाए।
IoC कंटेनर मैजिक नहीं है, और इसमें जावा ऑब्जेक्ट्स के बारे में जानने का कोई तरीका नहीं है जब तक कि आप किसी तरह से इसे सूचित नहीं करते हैं। जब आप कॉल करते हैं new
, तो JVM नई ऑब्जेक्ट की एक प्रति को तत्काल भेज देता है और इसे सीधे आपको सौंप देता है - यह कॉन्फ़िगरेशन प्रक्रिया से कभी नहीं जाता है। तीन तरीके हैं जिनसे आप अपने बीन्स को कॉन्फ़िगर कर सकते हैं।
मैंने इस GitHub परियोजना में लॉन्च करने के लिए स्प्रिंग बूट का उपयोग करते हुए इस कोड को पोस्ट किया है ; आप इसे काम करने के लिए आवश्यक हर चीज को देखने के लिए प्रत्येक दृष्टिकोण के लिए एक पूर्ण चल रहे प्रोजेक्ट को देख सकते हैं। इसके साथ टैग करें NullPointerException
:nonworking
अपनी फलियों को इंजेक्ट करें
सबसे बेहतर विकल्प यह है कि आप अपने सभी बीन्स को स्प्रिंग ऑटोवेयर करने दें; इसके लिए कम से कम कोड की आवश्यकता होती है और यह सबसे अधिक रखरखाव योग्य है। जैसा आप चाहते थे, उसी MileageFeeCalculator
तरह से ऑटो-फायरिंग का काम करने के लिए :
@Controller
public class MileageFeeController {
@Autowired
private MileageFeeCalculator calc;
@RequestMapping("/mileage/{miles}")
@ResponseBody
public float mileageFee(@PathVariable int miles) {
return calc.mileageCharge(miles);
}
}
यदि आपको विभिन्न अनुरोधों के लिए अपनी सेवा वस्तु का एक नया उदाहरण बनाने की आवश्यकता है, तो आप अभी भी स्प्रिंग बीन स्कोप का उपयोग करके इंजेक्शन का उपयोग कर सकते हैं ।
टैग जो @MileageFeeCalculator
सेवा ऑब्जेक्ट को इंजेक्ट करके काम करता है :working-inject-bean
@Configurable का उपयोग करें
यदि आपको वास्तव में new
स्वत: निर्मित होने वाली वस्तुओं की आवश्यकता है , तो आप अपनी वस्तुओं को इंजेक्ट करने के लिए एस्पेक्टज संकलन-समय की बुनाई के साथ स्प्रिंग @Configurable
एनोटेशन का उपयोग कर सकते हैं । यह दृष्टिकोण आपके ऑब्जेक्ट के कंस्ट्रक्टर में कोड सम्मिलित करता है जो स्प्रिंग को अलर्ट करता है कि यह बनाया जा रहा है ताकि स्प्रिंग नए उदाहरण को कॉन्फ़िगर कर सके। इसके लिए आपके बिल्ड में कॉन्फ़िगरेशन की थोड़ी आवश्यकता होती है (जैसे कि संकलन करना ajc
) और स्प्रिंग के रनटाइम कॉन्फ़िगरेशन हैंडलर ( @EnableSpringConfigured
JavaConfig सिंटैक्स के साथ ) को चालू करना । इस दृष्टिकोण का उपयोग रूओ एक्टिव रिकॉर्ड सिस्टम द्वारा किया जाता है ताकि new
आपकी संस्थाओं को आवश्यक दृढ़ता की जानकारी प्राप्त हो सके।
@Service
@Configurable
public class MileageFeeCalculator {
@Autowired
private MileageRateService rateService;
public float mileageCharge(final int miles) {
return (miles * rateService.ratePerMile());
}
}
@Configurable
सेवा ऑब्जेक्ट पर उपयोग करके काम करने वाला टैग :working-configurable
मैनुअल बीन लुकअप: अनुशंसित नहीं है
यह दृष्टिकोण केवल विशेष परिस्थितियों में विरासत कोड के साथ हस्तक्षेप करने के लिए उपयुक्त है। एक सिंगलटन एडॉप्टर क्लास बनाने के लिए लगभग हमेशा बेहतर होता है कि स्प्रिंग ऑटोवॉयर कर सकता है और विरासत कोड कॉल कर सकता है, लेकिन बीन के लिए स्प्रिंग एप्लिकेशन संदर्भ को सीधे पूछना संभव है।
ऐसा करने के लिए, आपको एक वर्ग की आवश्यकता होती है, जिसमें स्प्रिंग ApplicationContext
वस्तु का संदर्भ दे सके :
@Component
public class ApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getContext() {
return context;
}
}
तब आपका विरासत कोड कॉल कर सकता है getContext()
और इसके लिए आवश्यक सेम प्राप्त कर सकता है:
@Controller
public class MileageFeeController {
@RequestMapping("/mileage/{miles}")
@ResponseBody
public float mileageFee(@PathVariable int miles) {
MileageFeeCalculator calc = ApplicationContextHolder.getContext().getBean(MileageFeeCalculator.class);
return calc.mileageCharge(miles);
}
}
टैग जो वसंत संदर्भ में मैन्युअल रूप से सेवा ऑब्जेक्ट को देखकर काम करता है: working-manual-lookup
F
को दूसरे बीन के निर्माता के अंदर बुलाया जाता हैS
। इस मामलेF
में अन्य सेमS
कंस्ट्रक्टर के लिए एक पैरामीटर के रूप में आवश्यक बीन पास करें और केS
साथ कंस्ट्रक्टर को एनोटेट करें@Autowire
। केF
साथ पहली बीन के वर्ग को एनोटेट करना याद रखें@Component
।