Yanıtlar:
çünkü kurucu çağrıldığında, fasulye henüz başlatılmamıştır - yani hiçbir bağımlılık enjekte edilmemiştir. Gelen @PostConstruct
yöntemle fasulye tam olarak başlatılmadan ve bağımlılıkları kullanabilirsiniz.
çünkü bu, bu yöntemin fasulye yaşam döngüsünde sadece bir kez uygulanmasını garanti eden bir sözleşmedir. Bir çekirdeğin, iç işleyişinde kap tarafından birden çok kez başlatılması (olası olmasa da) olabilir, ancak @PostConstruct
yalnızca bir kez çağrılmasını garanti eder .
Ana sorun şudur:
bir kurucuda, bağımlılıkların enjeksiyonu henüz gerçekleşmemiştir *
* Konstrüktör Enjeksiyonu hariç
Gerçek dünya örneği:
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
}
}
ÖNEMLİ :
@PostConstruct
ve @PreDestroy
tamamen edilmiş Java 11'de çıkarıldı .
Bunları kullanmaya devam etmek için bağımlılıklarınıza javax.annotation-api JAR eklemeniz gerekir .
<!-- 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.
ayarlayıcı veya alan enjeksiyonuyla doğru, ancak yapıcı enjeksiyonuyla doğru değil.
Sınıfınız tüm başlatmasını yapıcıda gerçekleştirirse, @PostConstruct
gerçekten gereksizdir.
Ancak, sınıfınızın bağımlılıkları ayarlayıcı yöntemleri kullanılarak enjekte edilmişse, sınıfın yapıcısı nesneyi tam olarak başlatamaz ve bazen tüm ayarlayıcı yöntemleri çağrıldıktan sonra bazı başlatma işlemlerinin gerçekleştirilmesi gerekir @PostConstruct
.
Aşağıdaki senaryoyu düşünün:
public class Car {
@Inject
private Engine engine;
public Car() {
engine.initialize();
}
...
}
Otomobilin saha enjeksiyonundan önce başlatılması gerektiğinden, enjeksiyon noktası motoru yapıcı yürütülürken hala boştur ve sonuçta NullPointerException oluşur.
Bu sorun, Java yapıcı enjeksiyonu için JSR-330 Bağımlılık Enjeksiyonu veya Java @PostConstruct yöntemi ek açıklaması için JSR 250 Ortak Ek Açıklamaları ile çözülebilir .
@PostConstruct
JSR-250, Java SE 6'da bulunan yaygın bir ek açıklama kümesini tanımlar.
PostConstruct ek açıklaması, herhangi bir başlatma gerçekleştirmek için bağımlılık enjeksiyonu yapıldıktan sonra yürütülmesi gereken bir yöntemde kullanılır. Sınıf kullanılmadan önce bu yöntem çağrılmalıdır ZORUNLU. Bu açıklama bağımlılık enjeksiyonunu destekleyen tüm sınıflarda desteklenmelidir ZORUNLU.
JSR-250 Bölüm. 2.5 javax.nono.PostConstruct
@PostConstruct ek açıklaması, örnek başlatıldıktan ve tüm enjeksiyonlar gerçekleştirildikten sonra yürütülecek yöntemlerin tanımına izin verir.
public class Car {
@Inject
private Engine engine;
@PostConstruct
public void postConstruct() {
engine.initialize();
}
...
}
Yapıcıda başlatmayı gerçekleştirmek yerine, kod @PostConstruct ile açıklamalı bir yönteme taşınır.
İnşaat sonrası yöntemlerin işlenmesi, @PostConstruct ile açıklamalı tüm yöntemleri bulmak ve bunları sırayla çağırmak için basit bir konudur.
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);
}
});
}
Yapım sonrası yöntemlerin işlenmesi, örnekleme ve enjeksiyon tamamlandıktan sonra gerçekleştirilmelidir.
final
. Bu model göz önüne alındığında, neden@PostConstruct
J2EE'ye ekleniyor - mutlaka başka bir kullanım durumu görmüş olmalılar?