เหตุใดฉันจึงต้องมีตัวตั้งค่าสำหรับฟิลด์แบบ autowired / injected

ฉันมีถั่ว:

    <bean id="BasketLogic" class="efco.logic.EfcoBasketLogic" autowire="byType">
        <property name="documentLogic" ref="DocumentLogic" />
        <property name="stateAccess" ref="StateAccess" />
        <property name="contextAccess" ref="ContextAccess" />
    </bean>

  <bean id="EfcoErpService" autowire="byType" class="efco.erp.service.EfcoErpServiceImpl">
    <constructor-arg ref="ErpConnector"/>
  </bean>

documentLogic, stateAccess และ contextAccess เป็นช่องใน BasketLogicImpl

และฉันไม่มี <context:component-scan />

EfcoBasketLogic.java:

public class EfcoBasketLogic extends BasketLogicImpl {

        @Inject
        private EfcoErpService erpService;
    ...
    ...
    ...
}

erpService เป็น null เว้นแต่ฉันจะระบุตัวตั้งค่าไว้ แต่ทำไม? ฉันคิดว่าไม่จำเป็นต้องใช้ตัวตั้งค่าเมื่อมีการเดินสายอัตโนมัติ เป็นไปได้ไหมที่ BasketLogicImpl รับผิดชอบเรื่องนั้น


person GarfieldKlon    schedule 02.11.2012    source แหล่งที่มา


คำตอบ (3)


คุณต้องใช้ตัวตั้งค่า เนื่องจากระบบตรวจไม่พบคำอธิบายประกอบ เว้นแต่จะมีการแจ้งสปริงผ่าน <context:component-scan /> หรือ <context:annotation-config /> ตรวจพบตัวตั้งค่าเนื่องจากคุณระบุ autowire="byType"

คุณอาจพบว่าคำถามและคำตอบนี้มีประโยชน์เช่นกัน: เมื่อใดจึงควรใช้การเดินสายอัตโนมัติใน ฤดูใบไม้ผลิ

person mrembisz    schedule 02.11.2012
comment
หากฉันทำเช่นนั้น ปัญหาใหม่จะปรากฏขึ้น --> ไม่มีการกำหนด bean เฉพาะประเภท [xyz]: คาดว่า bean ที่ตรงกันเดี่ยว แต่พบ 5 นั่นเกิดจาก bean อื่นที่ฉันฉีดคุณสมบัติอย่างชัดเจนผ่าน <property name="x" ref="y"> และมี 5 bean ที่ใช้อินเทอร์เฟซนั้น คุณสมบัติ 'x' มีคำอธิบายประกอบ @Inject ดูเหมือนว่าการกำหนดที่ชัดเจนจะไม่แทนที่สิ่งที่มีสายอัตโนมัติใช่ไหม - person GarfieldKlon; 02.11.2012
comment
@Inject จะได้รับการแก้ไขอย่างถูกต้องหากมี bean ประเภทที่กำหนดเพียงอันเดียวหรืออันหนึ่งที่ทำเครื่องหมายว่าเป็นประเภทหลัก หากคุณมี bean ประเภทนั้นที่เปลี่ยนได้หลายอัน คุณจะต้องฉีดด้วยชื่อโดยใช้ @Resource หรือ xml - person mrembisz; 02.11.2012
comment
แม้ว่าฉันจะฉีด bean นั้นอย่างชัดเจนผ่าน <property name="..." ref="..."> ก็ตาม - person GarfieldKlon; 02.11.2012
comment
ฉันแนะนำให้ถามคำถามอื่น ฉันได้ตอบคำถามเดิมของคุณแล้ว และไม่สามารถเข้าใจได้ว่าปัญหาต่อไปของคุณคืออะไร หากไม่มีคำอธิบายโดยละเอียดเพิ่มเติม รวมถึงโค้ดหรือ xml - person mrembisz; 02.11.2012
comment
คำถามของฉันคือทำไมฉันต้องเขียนตัวตั้งค่า (เมื่อฉันไม่ได้ใช้การสแกนส่วนประกอบหรือคำอธิบายประกอบ-config) - person GarfieldKlon; 02.11.2012
comment
ตกลง แต่ทำไมฉันต้องเขียน setter ถ้าฉันใช้ autowire=byType และใส่คำอธิบายประกอบฟิลด์ด้วย @Inject ตั้งใจไว้แล้วมีทางไปไหม? ฉันหมายความว่าฉันสามารถทิ้งตัวตั้งค่าได้หากฉันจะใช้ annotation-config ดังนั้นจึงมีความแตกต่างระหว่างมันกับ autowire=byType? - person GarfieldKlon; 02.11.2012
comment
การเดินสายอัตโนมัติจะตรวจจับตัวตั้งค่าและพารามิเตอร์คอนสตรัคเตอร์ว่าเป็นการพึ่งพาที่อาจเกิดขึ้น ไม่ใช่สนามส่วนตัว คำอธิบายประกอบจะมองไม่เห็น เว้นแต่คุณต้องการให้มีการตรวจสอบคำอธิบายประกอบ - person mrembisz; 02.11.2012

ก่อนอื่น การใช้ <context:component-scan /> หรือ <context:annotation-config /> จะทำให้ Spring สามารถสแกนโค้ดของคุณเพื่อหา bean ที่มีสิทธิ์เพื่อให้เป็นไปตามการขึ้นต่อกัน ซึ่งจะปรับปรุงความสามารถในการโยงพวกมันได้อย่างถูกต้อง ดังนั้น ฉันขอแนะนำให้เพิ่มพวกมันลงในไฟล์บริบทของคุณ

ประการที่สอง คุณควรทราบว่า @Inject เป็นคำอธิบายประกอบมาตรฐาน (หมายถึงข้อกำหนด JSR-330) คุณสามารถผสมและจับคู่คำอธิบายประกอบ Spring กับคำอธิบายประกอบมาตรฐานได้ แต่ลักษณะการทำงานอาจแตกต่างกันไปเมื่อทำเช่นนั้น โดยทั่วไป @Named จะจับคู่กับ @Inject เพื่อจับคู่ส่วนประกอบที่มีการขึ้นต่อกัน (ทั้ง JSR-330) ดูข้อมูลอ้างอิงนี้ สำหรับรายละเอียด และดูตาราง 4.6 สำหรับความคิดเห็นเกี่ยวกับการใช้งาน

แต่เพื่อตอบคำถามของคุณโดยตรง "เหตุใดฉันจึงต้องมีตัวตั้งค่าเมื่อไม่ได้ใช้การสแกนส่วนประกอบ" นั้น เพราะ คุณไม่ได้ใช้การสแกนส่วนประกอบ คุณกำลังขอให้ Spring ฉีดการพึ่งพา "byType" แต่ไม่อนุญาตให้ Spring สแกนโค้ดของคุณเพื่อหาส่วนประกอบที่เป็นประเภทนั้น เหตุผลที่ setter ทำงานก็คือ Spring สามารถค้นพบประเภทของอาร์กิวเมนต์ setter ที่ถูกฉีดได้ในโค้ดไบต์ที่คอมไพล์แล้ว (เช่น meta-data) และดังนั้นจึงแก้ไขคำขอของคุณได้สำเร็จ

person pmhargis    schedule 03.09.2013
comment
โปรดทราบ: เมื่อใช้ ` ‹context:component-scan /› ` ตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่าแอตทริบิวต์แพ็กเกจฐานที่รากของลำดับชั้นคลาสของคุณซึ่งมีการประกาศคลาส bean (ผ่าน @Named หรือ @Autowired) ตัวอย่างเช่น: ‹beans› ‹context:component-scan base-package=org.example/› ‹/beans› - person pmhargis; 03.09.2013

ความเข้าใจของฉันคือการกำหนดค่า XML จะแทนที่การกำหนดค่าคำอธิบายประกอบ ความจริงที่ว่า autowire="byType" ที่ระบุจะแทนที่การฉีดอัตโนมัติ ซึ่งมองหาวิธีการ setter สำหรับการฉีดการพึ่งพา

person kbk    schedule 13.04.2016