ใน bean ที่@PostConstruct
ถูกจัดการจะถูกเรียกใช้หลังจากตัวสร้างอ็อบเจ็กต์ Java ปกติ
ทำไมฉันจะใช้@PostConstruct
เพื่อเริ่มต้นโดยถั่วแทนนวกรรมิกตัวเอง?
ใน bean ที่@PostConstruct
ถูกจัดการจะถูกเรียกใช้หลังจากตัวสร้างอ็อบเจ็กต์ Java ปกติ
ทำไมฉันจะใช้@PostConstruct
เพื่อเริ่มต้นโดยถั่วแทนนวกรรมิกตัวเอง?
คำตอบ:
เพราะเมื่อมีการเรียกตัวสร้างถั่วยังไม่ได้เริ่มต้น - นั่นคือไม่มีการพึ่งพาการฉีด ใน@PostConstruct
วิธีการนั้นถั่วจะเริ่มต้นได้อย่างสมบูรณ์และคุณสามารถใช้การอ้างอิง
เพราะนี่คือสัญญาที่รับประกันว่าวิธีนี้จะถูกเรียกใช้เพียงครั้งเดียวในวงจรชีวิตของถั่ว มันอาจเกิดขึ้น (แต่ไม่น่าเป็นไปได้) ว่าถั่วถูกสร้างอินสแตนซ์หลายครั้งโดยคอนเทนเนอร์ในการทำงานภายใน แต่รับประกันได้ว่า@PostConstruct
จะถูกเรียกใช้เพียงครั้งเดียว
หลักปัญหาคือว่า:
ในนวกรรมิกการฉีดของการพึ่งพายังไม่เกิดขึ้น *
* ไม่รวม Constructor Injection
ตัวอย่างโลกแห่งความจริง:
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
และ@PreDestroy
ได้รับสมบูรณ์ลบออกในชวา 11
หากต้องการใช้ต่อไปคุณจะต้องเพิ่ม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.
เป็นจริงด้วยตัวตั้งค่าหรือการฉีดภาคสนาม แต่ไม่เป็นจริงด้วยการสร้างตัวสร้าง
หากคลาสของคุณทำการเริ่มต้นทั้งหมดใน Constructor นั้น@PostConstruct
จะซ้ำซ้อนแน่นอน
อย่างไรก็ตามหากคลาสของคุณมีการพึ่งพาการฉีดโดยใช้เมธอด setter คอนสตรัคเตอร์ของคลาสจะไม่สามารถเริ่มต้นวัตถุได้อย่างสมบูรณ์และบางครั้งการกำหนดค่าเริ่มต้นบางอย่างจำเป็นต้องดำเนินการหลังจากเรียกเมธอด setter ทั้งหมด@PostConstruct
แล้ว
พิจารณาสถานการณ์สมมติต่อไปนี้:
public class Car {
@Inject
private Engine engine;
public Car() {
engine.initialize();
}
...
}
เนื่องจากต้องให้อินสแตนซ์ของรถยนต์ก่อนการฉีดภาคสนามเครื่องยนต์จุดฉีดจึงยังคงว่างในระหว่างการทำงานของตัวสร้างซึ่งส่งผลให้ NullPointerException
ปัญหานี้สามารถแก้ไขได้โดยJSR-330 Dependency Injection สำหรับ Java constructor injection หรือ JSR 250 คำอธิบายประกอบทั่วไปสำหรับคำอธิบายประกอบวิธีการ Java @PostConstruct
@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);
}
});
}
การประมวลผลของวิธีการหลังการก่อสร้างจะต้องดำเนินการหลังจาก instantiation และฉีดเสร็จสมบูรณ์
การกำหนดค่าเริ่มต้นตามคอนสตรัคเตอร์จะไม่ทำงานตามที่ตั้งใจเมื่อใดก็ตามที่เกี่ยวข้องกับพร็อกซีหรือ remoting บางชนิด
ct จะถูกเรียกเมื่อใดก็ตามที่ EJB ถูก deserialized และเมื่อใดก็ตามที่มีการสร้างพรอกซีใหม่สำหรับมัน ...
final
ผมประทับใจที่ฉีดคอนสตรัคเป็นที่นิยมโดยทั่วไปจะช่วยให้การอ้างอิงที่จะเป็น เมื่อพิจารณาถึงรูปแบบนั้นเหตุใดจึง@PostConstruct
ถูกเพิ่มใน J2EE - พวกเขาต้องเห็นกรณีการใช้งานอื่นอย่างแน่นอน?