<context:annotation-config>
wird verwendet, um Anmerkungen in Beans zu aktivieren, die bereits im Anwendungskontext registriert sind (unabhängig davon, ob sie mit XML oder durch Paketscanning definiert wurden).
<context:component-scan>
kann auch tun, was <context:annotation-config>
tut, aber <context:component-scan>
auch Pakete scannen, um Beans im Anwendungskontext zu finden und zu registrieren.
Ich werde einige Beispiele verwenden, um die Unterschiede / Ähnlichkeiten zu zeigen.
Fängt sich mit einer Grundeinstellung von drei Bohnen vom Typ beginnen A
, B
und C
mit B
und C
in injiziert werden A
.
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;
}
}
Mit folgender XML-Konfiguration:
<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>
Das Laden des Kontexts erzeugt die folgende Ausgabe:
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
OK, dies ist die erwartete Ausgabe. Aber das ist Frühling im "alten Stil". Jetzt haben wir Anmerkungen, also lassen Sie uns diese verwenden, um das XML zu vereinfachen.
Lassen Sie uns zunächst die bbb
und ccc
-Eigenschaften auf Bean A
wie folgt automatisch verdrahten :
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;
}
}
Dadurch kann ich die folgenden Zeilen aus dem XML entfernen:
<property name="bbb" ref="bBean" />
<property name="ccc" ref="cBean" />
Mein XML ist jetzt so vereinfacht:
<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />
Wenn ich den Kontext lade, erhalte ich folgende Ausgabe:
creating bean B: com.xxx.B@5e5a50
creating bean C: com.xxx.C@54a328
creating bean A: com.yyy.A@a3d4cf
OK, das ist falsch! Was ist passiert? Warum sind meine Immobilien nicht automatisch verdrahtet?
Nun, Anmerkungen sind eine nette Funktion, aber für sich genommen tun sie überhaupt nichts. Sie kommentieren nur Sachen. Sie benötigen ein Verarbeitungswerkzeug, um die Anmerkungen zu finden und etwas damit zu tun.
<context:annotation-config>
zur Rettung. Dadurch werden die Aktionen für die Anmerkungen aktiviert, die auf den Beans gefunden werden, die im selben Anwendungskontext definiert sind, in dem sie selbst definiert sind.
Wenn ich mein XML in Folgendes ändere:
<context:annotation-config />
<bean id="bBean" class="com.xxx.B" />
<bean id="cBean" class="com.xxx.C" />
<bean id="aBean" class="com.yyy.A" />
Wenn ich den Anwendungskontext lade, erhalte ich das richtige Ergebnis:
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
OK, das ist schön, aber ich habe zwei Zeilen aus dem XML entfernt und eine hinzugefügt. Das ist kein großer Unterschied. Die Idee mit Anmerkungen ist, dass es das XML entfernen soll.
Entfernen wir also die XML-Definitionen und ersetzen sie alle durch Anmerkungen:
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;
}
}
Während wir im XML sind, behalten wir nur Folgendes bei:
<context:annotation-config />
Wir laden den Kontext und das Ergebnis ist ... Nichts. Es werden keine Bohnen erstellt, keine Bohnen werden automatisch verdrahtet. Nichts!
Das liegt daran, dass, wie ich im ersten Absatz sagte, die <context:annotation-config />
einzige Funktion für Beans funktioniert , die im Anwendungskontext registriert sind. Da ich die XML-Konfiguration für die drei Beans entfernt habe, wurde keine Bean erstellt und es <context:annotation-config />
gibt keine "Ziele", an denen gearbeitet werden kann.
Dies ist jedoch kein Problem, bei <context:component-scan>
dem ein Paket nach "Zielen" durchsucht werden kann, an denen gearbeitet werden soll. Lassen Sie uns den Inhalt der XML-Konfiguration in den folgenden Eintrag ändern:
<context:component-scan base-package="com.xxx" />
Wenn ich den Kontext lade, erhalte ich folgende Ausgabe:
creating bean B: com.xxx.B@1be0f0a
creating bean C: com.xxx.C@80d1ff
Hmmmm ... etwas fehlt. Warum?
Wenn Sie sich die Klassen genau ansehen, hat die Klasse A
ein Paket, com.yyy
aber ich habe im <context:component-scan>
zu verwendenden Paket angegeben, com.xxx
dass dies meine A
Klasse völlig verfehlt und nur abgeholt hat B
und C
welche auf dem com.xxx
Paket sind.
Um dies zu beheben, füge ich auch dieses andere Paket hinzu:
<context:component-scan base-package="com.xxx,com.yyy" />
und jetzt bekommen wir das erwartete Ergebnis:
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
Und das ist es! Jetzt haben Sie keine XML-Definitionen mehr, sondern Anmerkungen.
Als letztes Beispiel, halten die kommentierten Klassen A
, B
und C
und die folgenden auf die XML, was wir bekommen nach dem Kontext geladen?
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />
Wir erhalten immer noch das richtige Ergebnis:
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
Auch wenn die Bean für die Klasse A
nicht durch Scannen erhalten wird, werden die Verarbeitungswerkzeuge weiterhin <context:component-scan>
auf alle im Anwendungskontext registrierten Beans angewendet , auch wenn A
diese manuell im XML registriert wurden.
Aber was ist, wenn wir das folgende XML haben, erhalten wir doppelte Beans, weil wir beide <context:annotation-config />
und angegeben haben <context:component-scan>
?
<context:annotation-config />
<context:component-scan base-package="com.xxx" />
<bean id="aBean" class="com.yyy.A" />
Nein, keine Duplikate. Wir erhalten wieder das erwartete Ergebnis:
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
Dies liegt daran, dass beide Tags dieselben Verarbeitungswerkzeuge registrieren ( <context:annotation-config />
kann weggelassen werden, wenn dies <context:component-scan>
angegeben ist), Spring jedoch dafür sorgt, dass sie nur einmal ausgeführt werden.
Selbst wenn Sie die Verarbeitungswerkzeuge mehrmals selbst registrieren, stellt Spring sicher, dass sie ihre Magie nur einmal ausführen. dieses 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" />
generiert weiterhin das folgende Ergebnis:
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
OK, das rappt es auf.
Ich hoffe, diese Informationen zusammen mit den Antworten von @Tomasz Nurkiewicz und @Sean Patrick Floyd sind alles, was Sie brauchen, um zu verstehen, wie <context:annotation-config>
und wie
<context:component-scan>
.