Jawaban:
karena ketika konstruktor dipanggil, kacang belum diinisialisasi - yaitu tidak ada ketergantungan yang disuntikkan. Dalam @PostConstruct
metode kacang sepenuhnya diinisialisasi dan Anda dapat menggunakan dependensi.
karena ini adalah kontrak yang menjamin bahwa metode ini akan dipanggil hanya sekali dalam siklus hidup kacang. Mungkin terjadi (walaupun tidak mungkin) bahwa sebuah kacang dipakai berkali-kali oleh wadah dalam pekerjaan internalnya, tetapi itu menjamin bahwa @PostConstruct
akan dipanggil hanya sekali.
Masalah utamanya adalah:
di konstruktor, injeksi dependensi belum terjadi *
* jelas tidak termasuk Injeksi Konstruktor
Contoh dunia nyata:
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
}
}
PENTING :
@PostConstruct
dan @PreDestroy
telah sepenuhnya dihapus di Jawa 11 .
Untuk tetap menggunakannya, Anda harus menambahkan Javax.annotation-api JAR ke dependensi Anda.
<!-- 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.
benar dengan setter atau injeksi lapangan, tetapi tidak benar dengan injeksi konstruktor.
Jika kelas Anda melakukan semua inisialisasi di konstruktor, maka @PostConstruct
memang berlebihan.
Namun, jika kelas Anda memiliki dependensi yang disuntikkan menggunakan metode setter, maka konstruktor kelas tidak dapat sepenuhnya menginisialisasi objek, dan kadang-kadang beberapa inisialisasi perlu dilakukan setelah semua metode setter dipanggil, maka kasus penggunaan @PostConstruct
.
Pertimbangkan skenario berikut:
public class Car {
@Inject
private Engine engine;
public Car() {
engine.initialize();
}
...
}
Karena Mobil harus dipakai sebelum injeksi lapangan, mesin titik injeksi masih nol selama pelaksanaan konstruktor, menghasilkan NullPointerException.
Masalah ini dapat dipecahkan dengan JSR-330 Dependency Injection untuk Java constructor injection atau JSR 250 Annotations untuk anotasi metode Java @PostConstruct.
@PostConstruct
JSR-250 mendefinisikan seperangkat penjelasan umum yang telah dimasukkan dalam Java SE 6.
Anotasi PostConstruct digunakan pada metode yang perlu dijalankan setelah injeksi dependensi dilakukan untuk melakukan inisialisasi. Metode ini HARUS dipanggil sebelum kelas dimasukkan ke dalam layanan. Anotasi ini HARUS didukung pada semua kelas yang mendukung injeksi ketergantungan.
JSR-250 Chap. 2.5 javax.annotation.PostConstruct
Anotasi @PostConstruct memungkinkan definisi metode yang akan dieksekusi setelah instantiated dan semua injeksi telah dilakukan.
public class Car {
@Inject
private Engine engine;
@PostConstruct
public void postConstruct() {
engine.initialize();
}
...
}
Alih-alih melakukan inisialisasi dalam konstruktor, kode tersebut dipindahkan ke metode yang dijelaskan dengan @PostConstruct.
Pemrosesan metode pasca-konstruksi adalah masalah sederhana untuk menemukan semua metode yang dijelaskan dengan @PostConstruct dan menjalankannya secara bergantian.
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);
}
});
}
Pemrosesan metode pasca-konstruksi harus dilakukan setelah instantiasi dan injeksi selesai.
final
. Mengingat pola itu, mengapa@PostConstruct
ditambahkan ke J2EE - mereka pasti melihat use case lain pasti?