Câu trả lời:
bởi vì khi hàm tạo được gọi, bean chưa được khởi tạo - tức là không có phần phụ thuộc nào được thêm vào. Trong @PostConstruct
phương thức, bean được khởi tạo hoàn toàn và bạn có thể sử dụng các phụ thuộc.
bởi vì đây là hợp đồng đảm bảo rằng phương thức này sẽ chỉ được gọi một lần trong vòng đời của bean. Có thể xảy ra (mặc dù không chắc) rằng một bean được khởi tạo nhiều lần bởi container trong hoạt động bên trong của nó, nhưng nó đảm bảo rằng nó @PostConstruct
sẽ chỉ được gọi một lần.
Các chính vấn đề là:
trong một hàm tạo, việc tiêm phụ thuộc chưa xảy ra *
* rõ ràng không bao gồm Con Contortor tiêm
Ví dụ thực tế:
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
}
}
QUAN TRỌNG :
@PostConstruct
và @PreDestroy
đã bị xóa hoàn toàn trong Java 11 .
Để tiếp tục sử dụng chúng, bạn sẽ cần thêm JAR javax.annotation-api vào phần phụ thuộc của mình.
<!-- 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.
đúng với setter hoặc tiêm trường, nhưng không đúng với tiêm constructor.
Nếu lớp của bạn thực hiện tất cả các khởi tạo của nó trong hàm tạo, thì @PostConstruct
thực sự là dư thừa.
Tuy nhiên, nếu lớp của bạn có các phụ thuộc được chèn bằng các phương thức setter, thì hàm tạo của lớp không thể khởi tạo hoàn toàn đối tượng và đôi khi một số khởi tạo cần được thực hiện sau khi tất cả các phương thức setter được gọi, do đó là trường hợp sử dụng @PostConstruct
.
Hãy xem xét kịch bản sau đây:
public class Car {
@Inject
private Engine engine;
public Car() {
engine.initialize();
}
...
}
Do Xe phải được khởi tạo trước khi tiêm trường, động cơ điểm tiêm vẫn không có giá trị trong quá trình thực thi của hàm tạo, dẫn đến NullPulumException.
Vấn đề này có thể được giải quyết bằng cách tiêm phụ thuộc JSR-330 cho phương thức tiêm của trình xây dựng Java hoặc Chú thích chung của JSR 250 cho chú thích phương thức Java @PostConstruct.
@PostConstruct
JSR-250 định nghĩa một tập hợp các chú thích phổ biến đã được đưa vào Java SE 6.
Chú thích PostConstruct được sử dụng trên một phương thức cần được thực thi sau khi thực hiện tiêm phụ thuộc để thực hiện bất kỳ khởi tạo nào. Phương thức này PHẢI được gọi trước khi lớp được đưa vào phục vụ. Chú thích này PHẢI được hỗ trợ trên tất cả các lớp hỗ trợ tiêm phụ thuộc.
JSR-250 Chap. 2.5 javax.annotation.PostConstruct
Chú thích @PostConstruct cho phép định nghĩa các phương thức được thực thi sau khi thể hiện đã được khởi tạo và tất cả các phép tiêm đã được thực hiện.
public class Car {
@Inject
private Engine engine;
@PostConstruct
public void postConstruct() {
engine.initialize();
}
...
}
Thay vì thực hiện khởi tạo trong hàm tạo, mã được chuyển sang một phương thức được chú thích bằng @PostConstruct.
Việc xử lý các phương thức hậu xây dựng là một vấn đề đơn giản là tìm tất cả các phương thức được chú thích bằng @PostConstruct và lần lượt gọi chúng.
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);
}
});
}
Việc xử lý các phương pháp sau xây dựng phải được thực hiện sau khi hoàn thành việc tiêm và tiêm.
final
. Với mô hình đó, tại sao lại@PostConstruct
được thêm vào J2EE - chắc chắn họ đã thấy một trường hợp sử dụng khác chắc chắn?