มีความแตกต่างระหว่างการใช้@PostConstructคำอธิบายประกอบและการประกาศวิธีเดียวกันกับการinit-methodกำหนดค่า Spring XML หรือไม่
มีความแตกต่างระหว่างการใช้@PostConstructคำอธิบายประกอบและการประกาศวิธีเดียวกันกับการinit-methodกำหนดค่า Spring XML หรือไม่
คำตอบ:
ไม่จริงฉันไม่คิดว่ามีความแตกต่าง แต่มีลำดับความสำคัญในวิธีการทำงาน @PostConstruct, init-methodมี BeanPostProcessors
@PostConstructเป็นคำอธิบายประกอบ JSR-250 ในขณะที่init-methodSpring เป็นวิธีการเริ่มต้น@PostConstructวิธีการนี้จะถูกเรียกก่อนที่จะเรียกวิธีการเริ่มต้นafterPropertiesSetแรก@PostConstructเรียกว่าแล้วแล้วafterPropertiesSetinit-methodสำหรับข้อมูลเพิ่มเติมคุณสามารถตรวจสอบของฤดูใบไม้ผลิเอกสารอ้างอิง
ก่อนหน้าข้อกำหนด JSR 250 การใช้วิธีการเริ่มต้นใน xml เป็นวิธีที่ต้องการเนื่องจากจะแยกคลาสจาวา (ถั่ว) ออกจากคลาส / คำอธิบายประกอบเฉพาะของฤดูใบไม้ผลิดังนั้นหากคุณกำลังสร้างไลบรารีที่ไม่จำเป็นต้องขึ้นอยู่กับโครงสร้างพื้นฐานของสปริงถั่ว จากนั้นจึงแนะนำให้ใช้วิธีการเริ่มต้นในระหว่างวิธีการสร้างคุณสามารถระบุวิธีการที่ต้องการเรียกเป็นวิธีการเริ่มต้น
ตอนนี้ด้วยการแนะนำข้อมูลจำเพาะ JSR 250 ใน Java EE และการรองรับสปริงของคำอธิบายประกอบเหล่านี้การพึ่งพาเฟรมเวิร์กสปริงจึงลดลงในระดับหนึ่ง
แต่ฉันต้องยอมรับว่าการเพิ่มสิ่งเหล่านี้เพิ่มความสามารถในการอ่านโค้ดดังนั้นจึงมีข้อดีและข้อเสียทั้งสองวิธี
ไม่มีความแตกต่างอย่างแท้จริง มันขึ้นอยู่กับว่าคุณต้องการกำหนดค่าระบบของคุณอย่างไรและนั่นเป็นเรื่องของทางเลือกส่วนบุคคล ตัวฉันเองฉันชอบที่จะใช้@PostConstructคำอธิบายประกอบสำหรับรหัสของฉันเอง (เนื่องจาก bean ได้รับการกำหนดค่าอย่างถูกต้องหลังจากเรียกเมธอดเท่านั้น) และฉันใช้init-methodเมื่อสร้างอินสแตนซ์ bean จากไลบรารีที่ไม่ทราบถึง Spring (ไม่สามารถใช้คำอธิบายประกอบได้ที่นั่นแน่นอน!) แต่ฉันเข้าใจคนที่ต้องการทำทั้งหมดไม่ทางใดก็ทางหนึ่ง
@postconstruct ไม่ได้เป็นส่วนหนึ่งของฤดูใบไม้ผลิ เป็นส่วนหนึ่งของแพ็คเกจ javax ทั้งสองอย่างเหมือนกัน โดยใช้ init-method เราจำเป็นต้องเพิ่มในไฟล์ xml หากคุณใช้ @postconstruct การเพิ่มใน xml ไม่จำเป็น ตรวจสอบบทความด้านล่าง
ที่คุณสามารถดูในแผนภาพด้านล่างของBean สร้างวงจรชีวิตโทรกลับ
3 ขั้นตอนนี้เกิดขึ้นใน Bean Creation Life-Cycle Callback:
@PostConstructจะเรียกว่าInitializingBeanมีการใช้งานแล้วafterPropertiesSet()จะเรียกinit-methodหรือ@Bean(initmethod="..")เรียกใช้เมธอด initแผนภาพนี้มาจากPro Spring 5: An In-Depth Guide to Spring Framework and its Tools
มีอาจจะมีความแตกต่างระหว่าง@PostConstructและinit-methodเพราะ @PostConstructมีการจัดการในpostProcessAfterInitializationขั้นตอนของการเริ่มต้นถั่ว ( AbstractAutowireCapableBeanFactory.initializeBean()วิธีการ) โดยCommonAnnotationBeanPostProcessorในขณะที่initวิธีการได้รับเรียกว่าหลังจากเสร็จสิ้นการpostProcessBeforeInitializationเฟส (และสำหรับเรื่องนี้ก่อนที่จุดเริ่มต้นของpostProcessAfterInitializationเฟส)
แก้ไข : ดังนั้นลำดับคือ 1) postProcessBeforeInitializationเฟส 2) initวิธีการถูกเรียก 3) postProcessAfterInitializationเฟสซึ่งเรียก@PostConstructเมธอด
(ในฐานะบันทึกด้านข้างคำแถลงจากคำตอบที่ยอมรับ
@PostConstruct, init-method คือ BeanPostProcessors
ไม่ได้ถูกต้องมาก: @PostConstructจะถูกจัดการโดยBeanPostProcessor, initวิธีการไม่ได้).
มีจะมีความแตกต่างถ้าบาง (อาจกำหนดเอง) BeanPostProcessorซึ่งถูกกำหนดค่าด้วย ( Ordered.getOrder()) ที่จะดำเนินการหลังจากที่CommonAnnotationBeanPostProcessorจะทำบางสิ่งบางอย่างร้ายแรงในของpostProcessBeforeInitializationวิธีการ
มีไม่มีความแตกต่างกับการกำหนดค่าฤดูใบไม้ผลิเริ่มต้นของใด ๆBeanPostProcessorsเพราะทุกBeanPostProcessorsที่มีการกำหนดค่าที่จะดำเนินการหลังจากที่CommonAnnotationBeanPostProcessorไม่ได้ทำอะไรในpostProcessBeforeInitializationวิธีการ
สรุปได้ว่าคำตอบที่ยอมรับและคำตอบที่คล้ายกันนั้นถูกต้อง ... ใน 99% ของกรณีและโพสต์นี้เป็นเพียงการแสดงความเคารพต่อแนวคิด "ปีศาจอยู่ในรายละเอียด"
รหัสเต็มที่นี่: https://github.com/wkaczurba/so8519187 ( spring-boot )
การใช้คำอธิบายประกอบ:
@Slf4j
@Component
public class MyComponent implements InitializingBean {
@Value("${mycomponent.value:Magic}")
public String value;
public MyComponent() {
log.info("MyComponent in constructor: [{}]", value); // (0) displays: Null
}
@PostConstruct
public void postConstruct() {
log.info("MyComponent in postConstruct: [{}]", value); // (1) displays: Magic
}
@Override // init-method; overrides InitializingBean.afterPropertiesSet()
public void afterPropertiesSet() {
log.info("MyComponent in afterPropertiesSet: [{}]", value); // (2) displays: Magic
}
@PreDestroy
public void preDestroy() {
log.info("MyComponent in preDestroy: [{}]", value); // (3) displays: Magic
}
}
รับเรา:
กำลังรีเฟรช org.springframework.context ...
MyComponent ในตัวสร้าง: [null]
MyComponent ใน postConstruct: [Magic]
MyComponent ใน afterPropertiesSet: [Magic]
... การ
ลงทะเบียนถั่วสำหรับการเปิดรับ JMX เมื่อเริ่มต้น
เริ่มต้น DemoApplication ใน 0.561 วินาที (JVM ทำงานเป็นเวลา 1.011) การ
ปิด org.springframework.context .. . กำลังยกเลิกการลงทะเบียนถั่วที่สัมผัส JMX เมื่อปิดเครื่อง
...
MyComponent ใน preDestroy: [Magic]