जवाबों:
क्योंकि जब कंस्ट्रक्टर को बुलाया जाता है, तो बीन को अभी तक इनिशियलाइज़ नहीं किया जाता है - यानी कोई भी निर्भरता इंजेक्ट नहीं की जाती है। में @PostConstruct
विधि सेम पूरी तरह से आरंभ और आप निर्भरता का उपयोग कर सकते हैं।
क्योंकि यह अनुबंध है जो गारंटी देता है कि यह विधि केवल एक बार बीन जीवन चक्र में लागू की जाएगी। ऐसा हो सकता है (हालांकि संभावना नहीं है) कि एक बीन को कंटेनर में कई बार उसके आंतरिक काम में @PostConstruct
लगाया जाता है , लेकिन यह गारंटी देता है कि इसे केवल एक बार ही लागू किया जाएगा।
मुख्य समस्या यह है कि यह है:
एक निर्माता में, निर्भरता का इंजेक्शन अभी तक नहीं हुआ है *
* स्पष्ट रूप से कंस्ट्रक्टर इंजेक्शन को छोड़कर
वास्तविक दुनिया का उदाहरण:
public class Foo {
@Inject
Logger LOG;
@PostConstruct
public void fooInit(){
LOG.info("This will be printed; LOG has already been injected");
}
public Foo() {
LOG.info("This will NOT be printed, LOG is still null");
// NullPointerException will be thrown here
}
}
महत्वपूर्ण :
@PostConstruct
और जावा 11 में@PreDestroy
पूरी तरह से हटा दिया गया है ।
उनका उपयोग करते रहने के लिए, आपको अपनी निर्भरताओं में javax.annotation-api JAR जोड़ने की आवश्यकता होगी ।
<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
// https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api
compile group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'
in a constructor, the injection of the dependencies has not yet occurred.
सेटर या फील्ड इंजेक्शन के साथ सही है, लेकिन कंस्ट्रक्टर इंजेक्शन के साथ सही नहीं है।
यदि आपकी कक्षा निर्माणकर्ता में अपनी सभी शुरुआत करती है, तो @PostConstruct
वास्तव में बेमानी है।
हालाँकि, यदि आपकी कक्षा में सेटर विधियों का उपयोग करके अपनी निर्भरताएँ इंजेक्ट की जाती हैं, तो क्लास का निर्माता पूरी तरह से ऑब्जेक्ट को इनिशियलाइज़ नहीं कर सकता है, और कभी-कभी सभी सेटर विधियों को कॉल करने के बाद कुछ इनिशियलाइज़ेशन की आवश्यकता होती है, इसलिए उपयोग का मामला @PostConstruct
।
इस परिदृश्य पर विचार करें:
public class Car {
@Inject
private Engine engine;
public Car() {
engine.initialize();
}
...
}
चूंकि फ़ील्ड इंजेक्शन से पहले कार को तत्काल किया जाना है, इंजेक्शन बिंदु इंजन कंस्ट्रक्टर के निष्पादन के दौरान अभी भी अशक्त है, जिसके परिणामस्वरूप NullPointerException है।
इस समस्या को Java कन्स्ट्रक्टर इंजेक्शन के लिए JSR-330 डिपेंडेंसी इंजेक्शन या Java @PostConstruct विधि एनोटेशन के लिए JSR 250 कॉमन एनोटेशन द्वारा हल किया जा सकता है ।
@PostConstruct
JSR-250 एनोटेशन के एक सामान्य सेट को परिभाषित करता है जिसे Java SE 6 में शामिल किया गया है।
PostConstruct एनोटेशन का उपयोग एक ऐसी विधि पर किया जाता है जिसे किसी भी आरंभीकरण को करने के लिए निर्भरता इंजेक्शन के बाद निष्पादित किया जाना चाहिए। वर्ग में सेवा में रखने से पहले इस विधि को लागू किया जाना चाहिए। यह एनोटेशन सभी वर्गों पर निर्भर होना चाहिए जो निर्भरता इंजेक्शन का समर्थन करते हैं।
JSR-250 चैप। 2.5 javax.annotation.PostConstruct
@PostConstruct एनोटेशन इंस्टेंस को इंस्टैंट करने के बाद निष्पादित किए जाने वाले तरीकों की परिभाषा के लिए अनुमति देता है और सभी इंजेक्शन का प्रदर्शन किया गया है।
public class Car {
@Inject
private Engine engine;
@PostConstruct
public void postConstruct() {
engine.initialize();
}
...
}
कन्स्ट्रक्टर में इनिशियलाइजेशन करने के बजाय, कोड को @PostConstruct के साथ एनोटेट करने की विधि में ले जाया जाता है।
निर्माण के बाद के तरीकों का प्रसंस्करण @PostConstruct के साथ एनोटेट किए गए सभी तरीकों को खोजने और बदले में उन्हें लागू करने का एक सरल मामला है।
private void processPostConstruct(Class type, T targetInstance) {
Method[] declaredMethods = type.getDeclaredMethods();
Arrays.stream(declaredMethods)
.filter(method -> method.getAnnotation(PostConstruct.class) != null)
.forEach(postConstructMethod -> {
try {
postConstructMethod.setAccessible(true);
postConstructMethod.invoke(targetInstance, new Object[]{});
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
throw new RuntimeException(ex);
}
});
}
इंस्टेंटेशन और इंजेक्शन के पूरा होने के बाद निर्माण के बाद के तरीकों का प्रसंस्करण किया जाना चाहिए।
final
। उस पैटर्न को देखते हुए,@PostConstruct
जे 2 ईई में क्यों जोड़ा जा रहा है - उन्होंने निश्चित रूप से एक और उपयोग मामला देखा होगा?