ความแตกต่างระหว่าง <context: annotation-config> และ <context: component-scan>


691

ฉันเรียนรู้ฤดูใบไม้ผลิ 3 และฉันดูเหมือนจะไม่เข้าใจที่อยู่เบื้องหลังการทำงานและ<context:annotation-config><context:component-scan>

จากสิ่งที่ผมเคยอ่านพวกเขาดูเหมือนจะจัดการที่แตกต่างกันคำอธิบายประกอบ ( @Required, @Autowiredฯลฯ VS @Component, @Repository, @Serviceฯลฯ ) แต่ยังมาจากสิ่งที่ผมเคยอ่านพวกเขาลงทะเบียนเดียวกันถั่วโพสต์ประมวลผลการเรียน

เพื่อสร้างความสับสนให้ฉันมากยิ่งขึ้นมีannotation-config แอตทริบิวต์<context:component-scan>บน

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


5
techidiocy.com/annotation-config-vs-component-scan-spring-coreนี่คือคำอธิบายที่ยอดเยี่ยม
VdeX

เพื่อสรุป: ใช้ component-scanเมื่อทำได้
Jerry Chin

คำตอบ:


1420

<context:annotation-config> ใช้เพื่อเปิดใช้งานคำอธิบายประกอบใน beans ที่ลงทะเบียนแล้วในบริบทแอปพลิเคชัน (ไม่ว่าจะถูกกำหนดด้วย XML หรือโดยการสแกนแพคเกจ)

<context:component-scan>ยังสามารถทำสิ่งที่<context:annotation-config>ทำได้ แต่<context:component-scan>สแกนแพ็กเกจเพื่อค้นหาและลงทะเบียน beans ภายในบริบทของแอปพลิเคชัน

ฉันจะใช้ตัวอย่างเพื่อแสดงความแตกต่าง / ความคล้ายคลึงกัน

ให้เริ่มต้นด้วยการตั้งค่าพื้นฐานของสามถั่วชนิดA, BและCด้วยBและถูกฉีดเข้าไปในCA

package com.xxx;
public class B {
  public B() {
    System.out.println("creating bean B: " + this);
  }
}

package com.xxx;
public class C {
  public C() {
    System.out.println("creating bean C: " + this);
  }
}

package com.yyy;
import com.xxx.B;
import com.xxx.C;
public class A { 
  private B bbb;
  private C ccc;
  public A() {
    System.out.println("creating bean A: " + this);
  }
  public void setBbb(B bbb) {
    System.out.println("setting A.bbb with " + bbb);
    this.bbb = bbb;
  }
  public void setCcc(C ccc) {
    System.out.println("setting A.ccc with " + ccc);
    this.ccc = ccc; 
  }
}

ด้วยการกำหนดค่า XML ต่อไปนี้:

<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A">
  <property name="bbb" ref="bBean" />
  <property name="ccc" ref="cBean" />
</bean>

การโหลดบริบทสร้างผลลัพธ์ต่อไปนี้:

creating bean B: com.xxx.B@c2ff5
creating bean C: com.xxx.C@1e8a1f6
creating bean A: com.yyy.A@1e152c5
setting A.bbb with com.xxx.B@c2ff5
setting A.ccc with com.xxx.C@1e8a1f6

ตกลงนี่คือผลลัพธ์ที่คาดหวัง แต่นี่คือ "แบบเก่า" ฤดูใบไม้ผลิ ตอนนี้เรามีคำอธิบายประกอบดังนั้นให้ใช้สิ่งเหล่านี้เพื่อทำให้ XML เป็นเรื่องง่ายขึ้น

ก่อนอื่นให้ autowire bbbและcccคุณสมบัติบน bean Aดังนี้:

package com.yyy;
import org.springframework.beans.factory.annotation.Autowired;
import com.xxx.B;
import com.xxx.C;
public class A { 
  private B bbb;
  private C ccc;
  public A() {
    System.out.println("creating bean A: " + this);
  }
  @Autowired
  public void setBbb(B bbb) {
    System.out.println("setting A.bbb with " + bbb);
    this.bbb = bbb;
  }
  @Autowired
  public void setCcc(C ccc) {
    System.out.println("setting A.ccc with " + ccc);
    this.ccc = ccc;
  }
}

สิ่งนี้ทำให้ฉันสามารถลบแถวต่อไปนี้ออกจาก XML:

<property name="bbb" ref="bBean" />
<property name="ccc" ref="cBean" />

XML ของฉันง่ายขึ้นในตอนนี้:

<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />

เมื่อฉันโหลดบริบทฉันจะได้ผลลัพธ์ต่อไปนี้:

creating bean B: com.xxx.B@5e5a50
creating bean C: com.xxx.C@54a328
creating bean A: com.yyy.A@a3d4cf

ตกลงนี่ผิด! เกิดอะไรขึ้น? เหตุใดคุณสมบัติของฉันจึงไม่ได้รับการตอบรับอัตโนมัติ

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

<context:annotation-config>ช่วยเหลือ. สิ่งนี้จะเปิดใช้งานการดำเนินการสำหรับคำอธิบายประกอบที่พบใน beans ที่กำหนดไว้ในบริบทแอปพลิเคชันเดียวกันกับที่กำหนดไว้

ถ้าฉันเปลี่ยน XML เป็น:

<context:annotation-config />
<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />

เมื่อฉันโหลดบริบทของแอปพลิเคชันฉันได้รับผลลัพธ์ที่ถูกต้อง:

creating bean B: com.xxx.B@15663a2
creating bean C: com.xxx.C@cd5f8b
creating bean A: com.yyy.A@157aa53
setting A.bbb with com.xxx.B@15663a2
setting A.ccc with com.xxx.C@cd5f8b

ตกลงนี่เป็นสิ่งที่ดี แต่ฉันได้ลบสองแถวออกจาก XML และเพิ่มหนึ่งแถว นั่นไม่ใช่ความแตกต่างที่ใหญ่มาก แนวคิดที่มีคำอธิบายประกอบคือควรลบ XML

ดังนั้นให้ลบนิยาม XML และแทนที่ทั้งหมดด้วยคำอธิบายประกอบ:

package com.xxx;
import org.springframework.stereotype.Component;
@Component
public class B {
  public B() {
    System.out.println("creating bean B: " + this);
  }
}

package com.xxx;
import org.springframework.stereotype.Component;
@Component
public class C {
  public C() {
    System.out.println("creating bean C: " + this);
  }
}

package com.yyy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.xxx.B;
import com.xxx.C;
@Component
public class A { 
  private B bbb;
  private C ccc;
  public A() {
    System.out.println("creating bean A: " + this);
  }
  @Autowired
  public void setBbb(B bbb) {
    System.out.println("setting A.bbb with " + bbb);
    this.bbb = bbb;
  }
  @Autowired
  public void setCcc(C ccc) {
    System.out.println("setting A.ccc with " + ccc);
    this.ccc = ccc;
  }
}

ในขณะที่อยู่ใน XML เราจะเก็บสิ่งนี้ไว้เท่านั้น:

<context:annotation-config />

เราโหลดบริบทและผลลัพธ์คือ ... ไม่มีอะไร ไม่มีการสร้างถั่วไม่มีการสร้างถั่วอัตโนมัติ ไม่มีอะไร!

นั่นเป็นเพราะอย่างที่ฉันได้กล่าวไว้ในย่อหน้าแรกการ<context:annotation-config />ทำงานกับ bean ที่ลงทะเบียนภายในบริบทของแอปพลิเคชันเท่านั้น เนื่องจากฉันลบการกำหนดค่า XML สำหรับถั่วสามตัวไม่มีการสร้าง bean และ<context:annotation-config />ไม่มี "เป้าหมาย" เพื่อทำงาน

แต่นั่นจะไม่เป็นปัญหา<context:component-scan>ที่สามารถสแกนแพคเกจสำหรับ "เป้าหมาย" เพื่อทำงาน มาเปลี่ยนเนื้อหาของการกำหนดค่า XML เป็นรายการต่อไปนี้:

<context:component-scan base-package="com.xxx" />

เมื่อฉันโหลดบริบทฉันจะได้ผลลัพธ์ต่อไปนี้:

creating bean B: com.xxx.B@1be0f0a
creating bean C: com.xxx.C@80d1ff

อืม ... มีบางอย่างขาดหายไป ทำไม?

ถ้าคุณมอง closelly ที่เรียนชั้นAมีแพคเกจcom.yyyแต่ฉันได้ระบุไว้ใน<context:component-scan>การใช้แพคเกจcom.xxxเพื่อให้สมบูรณ์พลาดของฉันนี้Aระดับและมีเพียงหยิบขึ้นมาBและCที่อยู่ในcom.xxxแพคเกจ

ในการแก้ไขปัญหานี้ฉันเพิ่มแพ็คเกจอื่นด้วย:

<context:component-scan base-package="com.xxx,com.yyy" />

และตอนนี้เราได้รับผลลัพธ์ที่คาดหวัง:

creating bean B: com.xxx.B@cd5f8b
creating bean C: com.xxx.C@15ac3c9
creating bean A: com.yyy.A@ec4a87
setting A.bbb with com.xxx.B@cd5f8b
setting A.ccc with com.xxx.C@15ac3c9

และนั่นมัน! ตอนนี้คุณไม่มีคำจำกัดความของ XML อีกต่อไปคุณมีคำอธิบายประกอบ

เป็นตัวอย่างสุดท้ายทำให้เรียนข้อเขียนA, BและCและการเพิ่มต่อไปนี้เพื่อ XML สิ่งที่เราจะได้รับหลังจากที่โหลดบริบท?

<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />

เรายังคงได้รับผลลัพธ์ที่ถูกต้อง:

creating bean B: com.xxx.B@157aa53
creating bean C: com.xxx.C@ec4a87
creating bean A: com.yyy.A@1d64c37
setting A.bbb with com.xxx.B@157aa53
setting A.ccc with com.xxx.C@ec4a87

แม้ว่า bean สำหรับคลาสAไม่ได้รับจากการสแกนเครื่องมือประมวลผลจะยังคงใช้<context:component-scan>กับ bean ทั้งหมดที่ลงทะเบียนในบริบทของแอปพลิเคชันแม้จะAลงทะเบียนด้วยตนเองใน XML

แต่ถ้าเรามี XML ต่อไปนี้จะเราได้รับถั่วซ้ำเพราะเราได้ระบุไว้ทั้งสอง<context:annotation-config />และ<context:component-scan>?

<context:annotation-config />
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />

ไม่ไม่ซ้ำเราได้ผลลัพธ์ที่คาดหวังอีกครั้ง:

creating bean B: com.xxx.B@157aa53
creating bean C: com.xxx.C@ec4a87
creating bean A: com.yyy.A@1d64c37
setting A.bbb with com.xxx.B@157aa53
setting A.ccc with com.xxx.C@ec4a87

นั่นเป็นเพราะแท็กทั้งสองลงทะเบียนเครื่องมือประมวลผลเดียวกัน ( <context:annotation-config />สามารถละเว้นได้หาก<context:component-scan>ระบุไว้) แต่สปริงจะดูแลการเรียกใช้เพียงครั้งเดียว

แม้ว่าคุณจะลงทะเบียนเครื่องมือประมวลผลด้วยตัวเองหลายครั้ง แต่สปริงก็ยังทำให้แน่ใจได้ว่าพวกเขาใช้เวทมนตร์เพียงครั้งเดียว XML นี้:

<context:annotation-config />
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />
<bean id="bla" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla1" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla2" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="bla3" class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />

จะยังคงสร้างผลลัพธ์ต่อไปนี้:

creating bean B: com.xxx.B@157aa53
creating bean C: com.xxx.C@ec4a87
creating bean A: com.yyy.A@25d2b2
setting A.bbb with com.xxx.B@157aa53
setting A.ccc with com.xxx.C@ec4a87

ตกลงว่าจะเคาะมันขึ้นมา

ฉันหวังว่าข้อมูลนี้มาพร้อมกับการตอบสนองจาก @Tomasz Nurkiewicz และ @Sean แพทริคฟลอยด์เป็นสิ่งที่คุณต้องเข้าใจวิธีการ <context:annotation-config>และ<context:component-scan>การทำงาน


8
อ้างอิง: "<context: annotation-config /> สามารถละเว้นได้หากระบุ <context: component-scan>" ทำไมจึงใช้คำอธิบายประกอบ -config แล้ว? ทำไมมันมีอยู่?
CodeClimber

2
คำตอบที่ดี! ไม่มีอะไรที่เหมือนกับตัวอย่างสั้น ๆ ที่ชัดเจนพร้อมคำอธิบายที่กระชับ เข้าใจทุกสิ่งในการอ่านครั้งเดียว
Jigish

19
ฉันขอให้คุณเขียนคู่มือฤดูใบไม้ผลิทั้งหมด! ส่วนที่ดีที่สุดของคำอธิบายเกี่ยวกับสิ่งที่เกี่ยวข้องกับ Spring Framework ที่สับสน ขอบคุณ
eskalera

7
คำอธิบายที่ง่ายและโดดเด่นมาก นอกจากการได้รับคำตอบแล้วฉันยังได้เรียนรู้วิธีที่ดีในการบอกสิ่งต่างๆ :)
Amir Al

2
สไตล์การเขียนของคุณนั้นง่ายมากสำหรับผู้เริ่มต้นที่จะเข้าใจ ฉันหวังว่าคุณจะสามารถเขียนหนังสือเกี่ยวกับ Spring พื้นฐาน ฉันสัญญาว่าจะซื้อ
emeraldhieu

167

ฉันพบข้อสรุปที่ดีซึ่งมีการเลือกคำอธิบายประกอบที่ประกาศ โดยการศึกษาคุณจะพบว่า<context:component-scan/>มีการเพิ่มบันทึกย่อประกอบที่ได้รับการยอมรับโดย<context:annotation-config/>กล่าวคือ:

  • @Component, @Service, @Repository, @Controller,@Endpoint
  • @Configuration, @Bean, @Lazy, @Scope, @Order, @Primary, @Profile, @DependsOn, @Import,@ImportResource

ในขณะที่คุณสามารถเห็น<context:component-scan/>เหตุผลขยาย <context:annotation-config/>ด้วยการสแกนองค์ประกอบ CLASSPATH และคุณสมบัติ Java @Configuration


16
@Tomasz ลิงก์ลง :(
Anand Rockzz

95

ฤดูใบไม้ผลิอนุญาตให้คุณทำสองสิ่ง:

  1. รับถั่วอัตโนมัติ
  2. ค้นหาอัตโนมัติของถั่ว

1. Autowiring
โดยปกติในapplicationContext.xmlคุณจะต้องกำหนด beans และถั่วอื่น ๆ โดยใช้วิธีการสร้างหรือวิธีการกำหนดค่า คุณสามารถโยงถั่วโดยใช้ XML หรือคำอธิบายประกอบ ในกรณีที่คุณใช้คำอธิบายประกอบคุณต้องเปิดใช้งานคำอธิบายประกอบและคุณจะต้องเพิ่ม <context:annotation-config />ในapplicationContext.xml สิ่งนี้จะทำให้โครงสร้างของแท็กง่ายขึ้นจากapplicationContext.xmlเนื่องจากคุณจะไม่ต้องต่อสายถั่วด้วยตัวเอง (Constructor หรือ Setter) คุณสามารถใช้@Autowireคำอธิบายประกอบและถั่วจะถูกต่อสายตามประเภท

ขั้นตอนต่อไปสำหรับการหลีกเลี่ยงการกำหนดค่า XML ด้วยตนเองคือ

2. Autodiscovery การค้นหาอัตโนมัติ
กำลังทำให้ XML ง่ายขึ้นอีกหนึ่งขั้นในแง่ที่ว่าคุณไม่จำเป็นต้องเพิ่ม<bean>แท็กในapplicationContext.xmlด้วยซ้ำ คุณเพียงแค่ทำเครื่องหมายถั่วเฉพาะด้วยคำอธิบายประกอบอย่างใดอย่างหนึ่งต่อไปนี้และสปริงจะผูกสายถั่วที่ทำเครื่องหมายไว้และการขึ้นต่อกันของพวกเขาลงในคอนเทนเนอร์ของสปริงโดยอัตโนมัติ คำอธิบายประกอบดังนี้ @Controller , @Service , @Component , @Repository เมื่อใช้<context:component-scan>และชี้ไปที่แพ็คเกจพื้นฐานสปริงจะค้นพบอัตโนมัติและเชื่อมต่อส่วนประกอบลงในคอนเทนเนอร์สปริง


สรุป:

  • <context:annotation-config />ถูกใช้เพื่อให้สามารถใช้ คำอธิบายประกอบ@Autowired
  • <context:component-scan /> ใช้เพื่อกำหนดการค้นหาของถั่วที่เฉพาะเจาะจงและความพยายามในการลงทะเบียนอัตโนมัติ

1
เป็นไปได้ไหมที่จะใช้การสแกนส่วนประกอบ แต่ไม่สามารถใส่คำอธิบายประกอบอย่างใด?
Koray Tugay

ใช้ annotation-config = "false" ในบริบท: แท็ก annotation-config
ซาร่า

38

<context:annotation-config> เปิดใช้งานคำอธิบายประกอบที่แตกต่างกันจำนวนมากในถั่วไม่ว่าจะถูกกำหนดไว้ใน XML หรือผ่านการสแกนส่วนประกอบ

<context:component-scan> ใช้สำหรับกำหนดถั่วโดยไม่ต้องใช้ XML

สำหรับข้อมูลเพิ่มเติมอ่าน:


คุณช่วยอธิบายเพิ่มเติมได้ไหม หากฉันใช้<context:component-scan>ฉันจะไม่สามารถแทนที่คำจำกัดความ bean โดยใช้ XML ได้หรือไม่
user938214097

@ user938214097 คุณสามารถกำหนด beans ใน XML หรือผ่านคำอธิบายประกอบด้วยการสแกนส่วนประกอบ
Sean Patrick Floyd

มันเพียงพอที่จะใช้<context:component-scan>หรือไม่ ฉันจะทำบางสิ่งบางอย่างหลวม ๆ ถ้าฉันไม่ได้ใช้<context:annotation-config>หรือไม่
user938214097

@Tomasz ดูเหมือนว่าจะได้รับคำตอบว่า
Sean Patrick Floyd

31

ความแตกต่างระหว่างทั้งสองนั้นง่ายมาก!

<context:annotation-config /> 

ช่วยให้คุณสามารถใช้คำอธิบายประกอบที่ จำกัด คุณสมบัติการเดินสายไฟและตัวสร้างถั่วเท่านั้น!

อยู่ที่ไหน

<context:component-scan base-package="org.package"/> 

ช่วยให้ทุกอย่างที่<context:annotation-config />สามารถทำได้ด้วยนอกเหนือจากการใช้แบบแผนเช่น .. @Component, ,@Service @Repositoryดังนั้นคุณสามารถเชื่อมโยงถั่วทั้งหมดและไม่ จำกัด เฉพาะตัวสร้างหรือคุณสมบัติ!


31

<context:annotation-config>:การสแกนและเปิดใช้งานคำอธิบายประกอบสำหรับ beans ที่ลงทะเบียนแล้วใน spring config xml

<context:component-scan>: การลงทะเบียน Bean +<context:annotation-config>


@Autowired และ @Requiredเป็นระดับคุณสมบัติเป้าหมายดังนั้น bean ควรลงทะเบียนใน spring IOC ก่อนใช้คำอธิบายประกอบเหล่านี้ ในการเปิดใช้งานคำอธิบายประกอบเหล่านี้ต้องลงทะเบียน beans หรือรวม<context:annotation-config />ไว้ เช่น<context:annotation-config />ทำงานกับถั่วที่ลงทะเบียนเท่านั้น

@Requiredช่วยให้ RequiredAnnotationBeanPostProcessor เครื่องมือในการประมวลผล
@Autowiredช่วยให้ AutowiredAnnotationBeanPostProcessorเครื่องมือในการประมวลผล

หมายเหตุ:หมายเหตุประกอบตัวเองไม่ต้องทำอะไรเราจำเป็นต้องมีเครื่องมือการประมวลผลซึ่งเป็นคลาสที่อยู่ข้างใต้ซึ่งรับผิดชอบกระบวนการหลัก


@Repository, @Service และ @Controller มี @Componentและพวกเขามีเป้าหมายระดับชั้น

<context:component-scan><context:annotation-config />มันจะสแกนแพคเกจและค้นหาและลงทะเบียนถั่วและจะมีงานที่ทำโดย

การโอนย้าย XML ไปยังคำอธิบายประกอบ


15

<context:annotation-config>แท็กบอกว่าฤดูใบไม้ผลิที่จะสแกน codebase สำหรับการแก้ไขข้อกำหนดที่พึ่งพาของชั้นเรียนที่มีคำอธิบายประกอบ @Autowired โดยอัตโนมัติ

Spring 2.5 ยังเพิ่มการรองรับคำอธิบายประกอบ JSR-250 เช่น @Resource, @PostConstruct และ @ PreDestroy การใช้คำอธิบายประกอบเหล่านี้ยังต้องการให้ BeanPostProcessors บางตัวต้องลงทะเบียนภายใน Spring container เช่นเคยสามารถลงทะเบียนเหล่านี้เป็นคำจำกัดความของถั่วแต่ละรายการ แต่ยังสามารถลงทะเบียนโดยนัยโดยรวม<context:annotation-config>แท็กในการกำหนดค่าสปริง

นำมาจากเอกสาร Spring ของการกำหนดค่าตามหมายเหตุประกอบ


Spring ให้ความสามารถในการตรวจจับคลาส 'stereotyped' โดยอัตโนมัติและลงทะเบียน BeanDefinitions ที่สอดคล้องกับ ApplicationContext

ตามที่ javadoc ของorg.springframework.stereotype :

แบบแผนคือคำอธิบายประกอบที่แสดงถึงบทบาทของประเภทหรือวิธีการในสถาปัตยกรรมโดยรวม (ที่แนวคิดมากกว่าการนำไปปฏิบัติระดับ) ตัวอย่าง: @Controller @Service @Repository ฯลฯ มีไว้สำหรับใช้งานโดยเครื่องมือและลักษณะ (ทำให้เป็นเป้าหมายในอุดมคติสำหรับจุดทางลัด)

หากต้องการตรวจสอบคลาส 'stereotype' โดยอัตโนมัติ<context:component-scan>จำเป็นต้องใช้แท็ก

<context:component-scan>แท็กยังบอกฤดูใบไม้ผลิในการสแกนรหัสสำหรับถั่วฉีดภายใต้แพคเกจ (และแพ็กเกจย่อยทั้งหมด) ที่ระบุไว้


14
<context:annotation-config>

เพียงแก้ไข@Autowiredและ@Qualiferคำอธิบายประกอบนั่นคือทั้งหมดที่มันเกี่ยวกับการฉีดพึ่งพามีคำอธิบายประกอบอื่น ๆ ที่ทำงานเดียวกันที่มีผมคิดว่าวิธีการ@Injectแต่ทั้งหมดที่เกี่ยวกับการแก้ปัญหา DI ผ่านคำอธิบายประกอบ

ระวังแม้ว่าคุณจะประกาศ<context:annotation-config>องค์ประกอบแล้วก็ตามคุณต้องประกาศคลาสของคุณว่า Bean เป็นอย่างไรโปรดจำไว้ว่าเรามีสามตัวเลือกให้เลือก

  • XML: <bean>
  • @Annotations: @Component, @Service, @Repository, @Controller
  • JavaConfig: @Configuration, @Bean

ตอนนี้ด้วย

<context:component-scan>

มันทำสองสิ่ง:

  • มันสแกนคลาสทั้งหมดที่มีคำอธิบายประกอบด้วย @Component, @Service, @Repository, @Controller และ @Configuration และสร้าง Bean
  • มันไม่ทำงานเดียวกันว่า<context:annotation-config>ไม่

ดังนั้นหากคุณประกาศ<context:component-scan>ไม่จำเป็นต้องประกาศอีกต่อไป<context:annotation-config>เช่นกัน

นั่นคือทั้งหมด

สถานการณ์ทั่วไปเป็นตัวอย่างเช่นประกาศ bean ผ่าน XML และแก้ไข DI ผ่านคำอธิบายประกอบตัวอย่างเช่น

<bean id="serviceBeanA" class="com.something.CarServiceImpl" />
<bean id="serviceBeanB" class="com.something.PersonServiceImpl" />
<bean id="repositoryBeanA" class="com.something.CarRepository" />
<bean id="repositoryBeanB" class="com.something.PersonRepository" />

เราได้ประกาศถั่วเท่านั้นไม่เกี่ยวกับ<constructor-arg>และ<property>DI ถูกกำหนดค่าในคลาสของตนเองผ่าน @Autowired มันหมายถึงบริการที่ใช้ @Autowired สำหรับส่วนประกอบที่เก็บข้อมูลของพวกเขาและที่เก็บข้อมูลที่ใช้ @Autowired สำหรับ JdbcTemplate, DataSource etc..components


1
คำอธิบายที่ยอดเยี่ยมขอบคุณ @Manuel Jordan
BALS

7
<context:component-scan /> implicitly enables <context:annotation-config/>

ลองด้วย<context:component-scan base-package="..." annotation-config="false"/>ใน@Serviceการกำหนดค่าของคุณ@Repository @Componentทำงานได้ดี แต่@ Autowired, @ Resourceและ@Injectไม่ทำงาน

ซึ่งหมายความว่าAutowiredAnnotationBeanPostProcessorจะไม่ถูกเปิดใช้งานและ Spring container จะไม่ประมวลผลคำอธิบายประกอบแบบ Autowiring


สิ่งนี้ช่วยให้ฉันเข้าใจว่า <context: component-scan /> เปิดใช้งานโดยปริยาย <context: annotation-config />; นั่นคือสแกนหาคำจำกัดความของถั่วรวมถึงการฉีดที่จำเป็น ฉันทดลองกับ annotation-config = "false" และการฉีดไม่ทำงานจนกว่าฉันจะตั้งค่าโดยใช้ <context: annotation-config /> ในที่สุดความเข้าใจของฉันก็ดีขึ้นกว่าเดิม!
CuriousMind

5
<context:annotation-config/> <!-- is used to activate the annotation for beans -->
<context:component-scan base-package="x.y.MyClass" /> <!-- is for the Spring IOC container to look for the beans in the base package. -->

จุดสำคัญอื่น ๆ ที่ควรทราบคือการcontext:component-scanเรียกใช้context:annotation-configเพื่อเปิดใช้งานคำอธิบายประกอบบน beans ดีถ้าคุณไม่ต้องการcontext:component-scanที่จะเปิดใช้งานโดยปริยายคำอธิบายประกอบสำหรับคุณคุณสามารถไปที่การตั้งค่าองค์ประกอบคำอธิบายประกอบ-config ของการcontext:component-scanfalse

เพื่อสรุป:

<context:annotation-config/> <!-- activates the annotations --> 
<context:component-scan base-package="x.y.MyClass" /> <!-- activates the annotations + register the beans by looking inside the base-package -->

1

<context:component-scan base-package="package name" />:

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

@Component, @Service, @Repository,@Controller

<context:annotation-config />:

หากเราไม่ต้องการเขียนถั่วแท็กอย่างชัดเจนใน XML แล้วภาชนะรู้ว่ามีสายไฟอัตโนมัติในถั่ว สิ่งนี้เป็นไปได้โดยใช้@Autowiredคำอธิบายประกอบ context:annotation-configเราจะต้องแจ้งไปยังคอนเทนเนอร์ที่มีการเดินสายไฟอัตโนมัติในถั่วของฉันโดย


0

<context:component-scan/>แท็กที่กำหนดเองลงทะเบียนชุดเดียวกับคำจำกัดความถั่วเป็นจะทำโดยนอกเหนือจากความรับผิดชอบหลักของการสแกนแพคเกจจาวาและลงทะเบียนคำจำกัดความถั่วจากคลาสพา ธ

หากด้วยเหตุผลบางอย่างการลงทะเบียนของนิยามถั่วเริ่มต้นนี้จะต้องหลีกเลี่ยงวิธีการทำเช่นนั้นคือการระบุแอตทริบิวต์ "annotation-config" เพิ่มเติมในการสแกนส่วนประกอบด้วยวิธีนี้:

<context:component-scan basePackages="" annotation-config="false"/>

การอ้างอิง: http://www.java-allandsundry.com/2012/12/12/contextcomponent-scan-contextannotation.html


0

<context:annotation-config>:

สิ่งนี้บอก Spring ว่าฉันจะใช้ Annotated beans เป็น spring bean และสิ่งเหล่านั้นจะถูกต่อสายผ่าน@Autowiredหมายเหตุประกอบแทนที่จะประกาศในไฟล์ spring config xml

<context:component-scan base-package="com.test..."> :

สิ่งนี้จะบอกถึงคอนเทนเนอร์ของสปริงซึ่งจะเริ่มค้นหาถั่วที่มีคำอธิบายประกอบ ฤดูใบไม้ผลิที่นี่จะค้นหาแพ็คเกจย่อยทั้งหมดของแพ็คเกจฐาน


0

คุณสามารถค้นหาข้อมูลเพิ่มเติมในไฟล์ schema บริบทฤดูใบไม้ผลิ ต่อไปนี้เป็น spring-context-4.3.xsd

<conxtext:annotation-config />
Activates various annotations to be detected in bean classes: Spring's @Required and
@Autowired, as well as JSR 250's @PostConstruct, @PreDestroy and @Resource (if available),
JAX-WS's @WebServiceRef (if available), EJB 3's @EJB (if available), and JPA's
@PersistenceContext and @PersistenceUnit (if available). Alternatively, you may
choose to activate the individual BeanPostProcessors for those annotations.

Note: This tag does not activate processing of Spring's @Transactional or EJB 3's
@TransactionAttribute annotation. Consider the use of the <tx:annotation-driven>
tag for that purpose.
<context:component-scan>
Scans the classpath for annotated components that will be auto-registered as
Spring beans. By default, the Spring-provided @Component, @Repository, @Service, @Controller, @RestController, @ControllerAdvice, and @Configuration stereotypes    will be detected.

Note: This tag implies the effects of the 'annotation-config' tag, activating @Required,
@Autowired, @PostConstruct, @PreDestroy, @Resource, @PersistenceContext and @PersistenceUnit
annotations in the component classes, which is usually desired for autodetected components
(without external configuration). Turn off the 'annotation-config' attribute to deactivate
this default behavior, for example in order to use custom BeanPostProcessor definitions
for handling those annotations.

Note: You may use placeholders in package paths, but only resolved against system
properties (analogous to resource paths). A component scan results in new bean definitions
being registered; Spring's PropertySourcesPlaceholderConfigurer will apply to those bean
definitions just like to regular bean definitions, but it won't apply to the component
scan settings themselves.

0

ในฐานะที่เป็นส่วนประกอบคุณสามารถใช้@ComponentScanเพื่อใช้<context:component-scan>ในการเพิ่มความคิดเห็น

มันอธิบายยังที่spring.io

กำหนดค่าคำสั่งการสแกนส่วนประกอบสำหรับใช้กับคลาส @Configuration ให้การสนับสนุนขนานกับองค์ประกอบของ Spring XML

สิ่งหนึ่งที่ควรทราบหากคุณใช้ Spring Boot @Configuration และ @ComponentScan สามารถบอกเป็นนัยได้โดยใช้คำอธิบายประกอบ @SpringBootApplication

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