Spring @PostConstruct เทียบกับแอตทริบิวต์ init-method


103

มีความแตกต่างระหว่างการใช้@PostConstructคำอธิบายประกอบและการประกาศวิธีเดียวกันกับการinit-methodกำหนดค่า Spring XML หรือไม่

คำตอบ:


153

ไม่จริงฉันไม่คิดว่ามีความแตกต่าง แต่มีลำดับความสำคัญในวิธีการทำงาน @PostConstruct, init-methodมี BeanPostProcessors

  1. @PostConstructเป็นคำอธิบายประกอบ JSR-250 ในขณะที่init-methodSpring เป็นวิธีการเริ่มต้น
  2. หากคุณมี@PostConstructวิธีการนี้จะถูกเรียกก่อนที่จะเรียกวิธีการเริ่มต้น
  3. หากการดำเนินการของคุณถั่ว InitializingBean และแทนที่afterPropertiesSetแรก@PostConstructเรียกว่าแล้วแล้วafterPropertiesSetinit-method

สำหรับข้อมูลเพิ่มเติมคุณสามารถตรวจสอบของฤดูใบไม้ผลิเอกสารอ้างอิง

ก่อนหน้าข้อกำหนด JSR 250 การใช้วิธีการเริ่มต้นใน xml เป็นวิธีที่ต้องการเนื่องจากจะแยกคลาสจาวา (ถั่ว) ออกจากคลาส / คำอธิบายประกอบเฉพาะของฤดูใบไม้ผลิดังนั้นหากคุณกำลังสร้างไลบรารีที่ไม่จำเป็นต้องขึ้นอยู่กับโครงสร้างพื้นฐานของสปริงถั่ว จากนั้นจึงแนะนำให้ใช้วิธีการเริ่มต้นในระหว่างวิธีการสร้างคุณสามารถระบุวิธีการที่ต้องการเรียกเป็นวิธีการเริ่มต้น

ตอนนี้ด้วยการแนะนำข้อมูลจำเพาะ JSR 250 ใน Java EE และการรองรับสปริงของคำอธิบายประกอบเหล่านี้การพึ่งพาเฟรมเวิร์กสปริงจึงลดลงในระดับหนึ่ง

แต่ฉันต้องยอมรับว่าการเพิ่มสิ่งเหล่านี้เพิ่มความสามารถในการอ่านโค้ดดังนั้นจึงมีข้อดีและข้อเสียทั้งสองวิธี


23
หากถั่วกำลังใช้มากกว่าหนึ่งในวิธีการเหล่านั้นและอาศัยลำดับการเริ่มต้นมันจะซับซ้อนอย่างน่ากลัวและไม่สามารถเข้าถึงได้
Donal Fellows

2
@Donal ค่อนข้างจริง เป็นเพียงการให้ข้อมูลเกี่ยวกับวิธีการทำงาน
Aravind A

1
มีความแตกต่างที่สำคัญ: คุณต้องกำหนดค่าเฉพาะ Spring เพื่อประมวลผลคำอธิบายประกอบเพื่อให้ @PostConstruct ทำงาน: stackoverflow.com/q/3434377/134898
Juan Calero

@DonalFellows แต่คุณต้องรู้สิ่งนี้หากคุณวางแผนที่จะสอบรับรอง;)
S.Klechkovski

@DonalFellows - คุณช่วยอธิบายคำตอบของคุณให้ละเอียดได้ไหม? ฉันหมายถึงความยากลำบากที่ต้องเผชิญหากถั่วขึ้นอยู่กับลำดับการเริ่มต้น จริงๆแล้วอยากรู้ว่าอันไหนดีกว่ากัน PostConstruct หรือ Bean (initMethod = "init") เพื่อทำการเริ่มต้นบางอย่างจาก bean ก่อนที่จะตอบสนองคำขอใด ๆ ?
Ayaskant

19

ไม่มีความแตกต่างอย่างแท้จริง มันขึ้นอยู่กับว่าคุณต้องการกำหนดค่าระบบของคุณอย่างไรและนั่นเป็นเรื่องของทางเลือกส่วนบุคคล ตัวฉันเองฉันชอบที่จะใช้@PostConstructคำอธิบายประกอบสำหรับรหัสของฉันเอง (เนื่องจาก bean ได้รับการกำหนดค่าอย่างถูกต้องหลังจากเรียกเมธอดเท่านั้น) และฉันใช้init-methodเมื่อสร้างอินสแตนซ์ bean จากไลบรารีที่ไม่ทราบถึง Spring (ไม่สามารถใช้คำอธิบายประกอบได้ที่นั่นแน่นอน!) แต่ฉันเข้าใจคนที่ต้องการทำทั้งหมดไม่ทางใดก็ทางหนึ่ง


4

@postconstruct ไม่ได้เป็นส่วนหนึ่งของฤดูใบไม้ผลิ เป็นส่วนหนึ่งของแพ็คเกจ javax ทั้งสองอย่างเหมือนกัน โดยใช้ init-method เราจำเป็นต้องเพิ่มในไฟล์ xml หากคุณใช้ @postconstruct การเพิ่มใน xml ไม่จำเป็น ตรวจสอบบทความด้านล่าง

http://answersz.com/spring-postconstruct-and-predestroy/


3

ที่คุณสามารถดูในแผนภาพด้านล่างของBean สร้างวงจรชีวิตโทรกลับ

การเรียกคืนวงจรชีวิตของ Bean Creation

3 ขั้นตอนนี้เกิดขึ้นใน Bean Creation Life-Cycle Callback:

  1. เป็นที่กล่าวขวัญกันว่า @PostConstructจะเรียกว่า
  2. หากInitializingBeanมีการใช้งานแล้วafterPropertiesSet()จะเรียก
  3. ถ้าคำจำกัดความของ bean มีinit-methodหรือ@Bean(initmethod="..")เรียกใช้เมธอด init

แผนภาพนี้มาจากPro Spring 5: An In-Depth Guide to Spring Framework and its Tools


3

มีอาจจะมีความแตกต่างระหว่าง@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% ของกรณีและโพสต์นี้เป็นเพียงการแสดงความเคารพต่อแนวคิด "ปีศาจอยู่ในรายละเอียด"


ไฮ! สิ่งนี้ทำให้เกิดความสับสนหาก PostConstruct ทำงานก่อน init-method จะจัดการอย่างไรโดย postProcessAfterInitialization ถ้าเมธอด init ทำงานหลังจาก postProcessBeforeInitialization และก่อน postProcessAfterInitialization ???
Maxrunner

@Maxrunner ขออภัยในความสับสนและขอบคุณมากที่แจ้งให้ทราบ! อันที่จริงฉันไม่เคยตั้งใจจะบอกว่า PostConstruct ทำงานก่อน init-method อย่างไรก็ตามฉันอัปเดตคำตอบของฉันพร้อมคำชี้แจง
igor.zh

2

รหัสเต็มที่นี่: 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]

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.