เรียกใช้วิธีการใส่คำอธิบายประกอบ @Bean ในการกำหนดค่า Spring java


102

ฉันอยากรู้ว่าการฉีดสปริงจัดการกับวิธีการโทรด้วย@Beanคำอธิบายประกอบอย่างไร ถ้าฉันใส่@Beanคำอธิบายประกอบในเมธอดและส่งคืนอินสแตนซ์ฉันเข้าใจว่าสิ่งนั้นบอกให้สปริงสร้าง bean โดยเรียกใช้เมธอดและรับอินสแตนซ์ที่ส่งคืน อย่างไรก็ตามบางครั้งถั่วนั้นจะต้องใช้ในการต่อสายถั่วอื่นหรือตั้งค่ารหัสอื่น วิธีปกติจะทำคือเรียกใช้@Beanวิธีการใส่คำอธิบายประกอบเพื่อรับอินสแตนซ์ คำถามของฉันคือเหตุใดสิ่งนี้จึงไม่ทำให้มีหลายอินสแตนซ์ของถั่วลอยอยู่รอบ ๆ ?

ตัวอย่างเช่นดูรหัสด้านล่าง (นำมาจากคำถามอื่น) entryPoint()วิธีการที่กำกับด้วย@Beanดังนั้นฉันจะคิดฤดูใบไม้ผลิที่จะสร้างตัวอย่างใหม่ของBasicAuthenticationEntryPointเป็นถั่ว จากนั้นเราจะเรียกentryPoint()อีกครั้งในการกำหนดค่าบล็อก แต่ดูเหมือนว่าentryPoint()จะส่งคืนอินสแตนซ์ bean และไม่ได้ถูกเรียกหลายครั้ง (ฉันพยายามบันทึกและได้รับรายการบันทึกเพียงรายการเดียว) เป็นไปได้ว่าเราสามารถเรียกใช้entryPoint()หลายครั้งในส่วนอื่น ๆ ของการกำหนดค่าและเราจะได้รับอินสแตนซ์เดียวกันเสมอ ความเข้าใจของฉันถูกต้องหรือไม่? ฤดูใบไม้ผลิมีการเขียนวิธีการใหม่ที่มีคำอธิบายประกอบด้วยมนต์ขลัง@Beanหรือไม่?

@Bean
public BasicAuthenticationEntryPoint entryPoint() {
    BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint();
    basicAuthEntryPoint.setRealmName("My Realm");
    return basicAuthEntryPoint;
}

@Override
protected void configure(HttpSecurity http) throws Exception {

    http
        .exceptionHandling()
            .authenticationEntryPoint(entryPoint())
            .and()
        .authorizeUrls()
            .anyRequest().authenticated()
            .and()
        .httpBasic();       
}

คำตอบ:


134

ใช่ฤดูใบไม้ผลิไม่บางมายากล ตรวจสอบเอกสาร Spring :

ซึ่งเป็นที่ที่วิเศษมาใน: ทุก@Configurationชั้นเรียนจะ subclassed ที่เริ่มต้นเวลากับCGLIB ในคลาสย่อยเมธอดลูกจะตรวจสอบคอนเทนเนอร์ก่อนสำหรับถั่วที่แคช (ขอบเขต) ก่อนที่จะเรียกใช้เมธอดพาเรนต์และสร้างอินสแตนซ์ใหม่

ซึ่งหมายความว่าการเรียกไปยัง@Beanเมธอดจะถูกพร็อกซีผ่านCGLIBดังนั้นเวอร์ชันที่แคชของ bean จะถูกส่งกลับ (ไม่ได้สร้างวิธีการใหม่)

ขอบเขตเริ่มต้นของ@Beans คือSINGLETONหากคุณระบุขอบเขตอื่นเช่นPROTOTYPEการโทรจะถูกส่งต่อไปยังเมธอดเดิม

โปรดทราบว่านี่คือไม่ถูกต้องสำหรับวิธีการคง ตามเอกสารฤดูใบไม้ผลิ:

การเรียกใช้@Beanเมธอดแบบคงที่จะไม่ถูกดักจับโดยคอนเทนเนอร์แม้แต่ใน@Configurationคลาส (ตามที่อธิบายไว้ก่อนหน้าในส่วนนี้) เนื่องจากข้อ จำกัด ทางเทคนิค: คลาสย่อย CGLIB สามารถแทนที่เฉพาะเมธอดที่ไม่คงที่ ด้วยเหตุนี้การเรียกโดยตรงไปยัง@Beanเมธอดอื่นจึงมีความหมาย Java มาตรฐานส่งผลให้อินสแตนซ์อิสระถูกส่งกลับโดยตรงจากเมธอดของโรงงาน


เป็นไปได้ไหมที่จะแทนที่ถั่วที่สร้างขึ้นด้วยวิธีนี้? ตัวอย่างเช่นฉันมีคลาสที่กำหนด Spring ซึ่งเรียกใช้วิธีการสร้าง bean โดยตรง สิ่งที่ฉันต้องการคือไม่ใช้ bean ที่สร้างโดยวิธีนั้น แต่เป็นสิ่งที่ฉันกำหนดเอง (โดยใส่คำอธิบายประกอบด้วย@Beanและ@Primary)
Fons

4
แต่ฉันยังจำได้ว่าพร็อกซี (jdk หรือ CGLIB แล้วแต่ข้อใด) ไม่สามารถทำงานในการเรียกใช้งานด้วยตนเองได้ดังนั้น @Configuration กำหนดการพึ่งพาระหว่างถั่วอย่างไร มันใช้การเรียกตัวเองเป๊ะ
ตอนนี้

3
@ CGLib allows us to create proxy classes at runtime by creating sub class of specified class using Byte code generation. CGLib proxies are used in the case where Proxy is to be created for those class which does not have any interfaces or have methods which are not declared in the implementing interface. ตอนนี้ในกรณีนี้ CGLIB จะสร้างคลาสย่อยของคลาส @Configuration และแทนที่เมธอดของมัน (รวมถึงเมธอด @Bean) ดังนั้นเมื่อเราเรียกเมธอด @Bean จากวิธีอื่นเราจึงเรียกมันว่า overriden version (ขอบคุณ java dynamic binding)
Flame239

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