วิธีสแกนหลายเส้นทางโดยใช้คำอธิบายประกอบ @ComponentScan


90

ฉันใช้ Spring 3.1 และบูตแอปพลิเคชันโดยใช้แอตทริบิวต์@Configurationand@ComponentScan

เริ่มต้นจริงด้วย

new AnnotationConfigApplicationContext(MyRootConfigurationClass.class);

คลาส Configuration นี้มีคำอธิบายประกอบ

@Configuration
@ComponentScan("com.my.package")
public class MyRootConfigurationClass

และใช้งานได้ดี อย่างไรก็ตามฉันต้องการเจาะจงมากขึ้นเกี่ยวกับแพ็คเกจที่ฉันสแกนดังนั้นฉันจึงลอง

@Configuration
@ComponentScan("com.my.package.first,com.my.package.second")
public class MyRootConfigurationClass

อย่างไรก็ตามสิ่งนี้ล้มเหลวโดยมีข้อผิดพลาดบอกฉันว่าไม่พบส่วนประกอบที่ระบุโดยใช้@Componentคำอธิบายประกอบ

วิธีที่ถูกต้องในการทำสิ่งที่ฉันต้องการคืออะไร?

ขอบคุณ


คำตอบที่ถูกต้องสองคำตอบในเวลาเดียวกันเท่าที่ฉันสามารถบอกได้ ฉันจะยอมรับที่จะเฮเพียงเพราะเขามีคะแนนน้อยกว่า แต่ขอบคุณทั้งสองคน
Programming Guy

หากคุณสงสัยในสิ่งเดียวกันสำหรับรุ่นkotlinตรวจสอบสิ่งนี้stackoverflow.com/a/62818187/7747942
Sylhare

คำตอบ:


161

@ComponentScanใช้อาร์เรย์สตริงเช่นนี้:

@ComponentScan({"com.my.package.first","com.my.package.second"})

เมื่อคุณระบุชื่อแพ็กเกจหลายชื่อในสตริงเดียว Spring จะตีความว่าชื่อแพ็กเกจนี้เป็นชื่อแพ็กเกจเดียวจึงไม่พบ


48

มีทางเลือกประเภท อื่นที่ปลอดภัยในการระบุตำแหน่งแพคเกจฐานเป็นสตริง ดู API ที่นี่แต่ฉันได้แสดงไว้ด้านล่าง:

@ComponentScan(basePackageClasses = {ExampleController.class, ExampleModel.class, ExmapleView.class})

การใช้ตัวระบุbasePackageClassesกับการอ้างอิงคลาสของคุณจะบอกให้ Spring สแกนแพ็กเกจเหล่านั้น (เช่นเดียวกับทางเลือกที่กล่าวถึง) แต่วิธีนี้ทั้งปลอดภัยและเพิ่มการรองรับ IDEสำหรับการอ้างอิงในอนาคตซึ่งเป็นข้อดีอย่างมากในหนังสือของฉัน

เมื่ออ่านจาก API Spring แนะนำให้สร้างคลาสหรืออินเทอร์เฟซของเครื่องหมาย no-op ในแต่ละแพ็คเกจที่คุณต้องการสแกนซึ่งไม่มีจุดประสงค์อื่นใดนอกจากใช้เป็นข้อมูลอ้างอิงสำหรับ / โดยแอตทริบิวต์นี้

IMO ฉันไม่ชอบคลาสเครื่องหมาย(แต่อีกครั้งพวกมันค่อนข้างเหมือนกับคลาสข้อมูลแพ็คเกจ)แต่ประเภทความปลอดภัยการรองรับ IDE และการลดจำนวนแพ็คเกจพื้นฐานที่จำเป็นสำหรับการสแกนนี้ลงอย่างมาก คือไม่ต้องสงสัยเลยว่าเป็นตัวเลือกที่ดีกว่ามาก


มีใครช่วยอธิบายได้ไหมว่าทำไม @ComponentScan ({"com.app", "com.controllers"}) ใช้ไม่ได้สำหรับฉัน แต่ @ComponentScan (basePackageClasses = {"com.controllers"}) ทำงานได้ดี ฉันคิดว่ามันน่าเบื่อในการเขียนชื่อชั้นเรียนทุกครั้ง
xaverras

3
คุณต้องระบุคลาสเดียวในแพ็กเกจสำหรับแพ็กเกจที่คุณต้องการสแกน สิ่งนี้เรียกว่าคลาสเครื่องหมาย หากคุณต้องการสแกนแพ็กเกจที่สูงขึ้นในลำดับชั้นที่ไม่มีคลาสสปริงแนะนำเทคนิคโดยใช้อินเทอร์เฟซ "สปริงมาร์กเกอร์" หรือคลาสสุดท้ายที่กำหนดไว้ในแพ็กเกจนั้นเพื่อวัตถุประสงค์ในการสแกนแพ็กเกจเท่านั้น
Prancer

17

ระบุชื่อแพ็กเกจของคุณแยกกันโดยต้องใช้String[]สำหรับชื่อแพ็กเกจ

แทนสิ่งนี้:

@ComponentScan("com.my.package.first,com.my.package.second")

ใช้สิ่งนี้:

@ComponentScan({"com.my.package.first","com.my.package.second"})

10

อีกวิธีหนึ่งในการทำเช่นนี้คือการใช้basePackagesฟิลด์ ซึ่งเป็นฟิลด์ภายในคำอธิบายประกอบ ComponentScan

@ComponentScan(basePackages={"com.firstpackage","com.secondpackage"})

หากคุณดูคำอธิบายประกอบ ComponentScan .class จากไฟล์ jar คุณจะเห็นฟิลด์ basePackages ที่ใช้ในอาร์เรย์ของสตริง

public @interface ComponentScan {
String[] basePackages() default {};
}

หรือคุณสามารถพูดถึงชั้นเรียนอย่างชัดเจน ซึ่งใช้เวลาในอาร์เรย์ของคลาส

Class<?>[]  basePackageClasses

4

คุณใช้ ComponentScan เพื่อสแกนหลายแพ็คเกจโดยใช้ไฟล์

@ComponentScan({"com.my.package.first","com.my.package.second"})


1

ตรวจสอบให้แน่ใจว่าคุณได้เพิ่มการอ้างอิงนี้ใน pom.xml ของคุณ

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

ขอบคุณหลังจากใช้เวลาเกือบครึ่งชั่วโมงนี่คือการพึ่งพาที่ขาดหายไป
DvixExtract

1

คุณยังสามารถใช้คำอธิบายประกอบ @ComponentScans:

@ComponentScans(value = { @ComponentScan("com.my.package.first"),
                          @ComponentScan("com.my.package.second") })

4
โปรดพิจารณาเพิ่มคำอธิบายในคำตอบของคุณ
Yeya

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