TL; DR
Die Annotation @Autowired erspart Ihnen die Verkabelung in der XML-Datei (oder auf andere Weise) selbst und findet nur für Sie, was wo injiziert werden muss, und erledigt dies für Sie.
Vollständige Erklärung
Mit der @Autowired
Anmerkung können Sie an anderer Stelle Konfigurationen überspringen, was injiziert werden soll, und dies nur für Sie tun. Angenommen, Ihr Paket besteht darin, dass com.mycompany.movies
Sie dieses Tag in Ihre XML-Datei (Anwendungskontextdatei) einfügen müssen:
<context:component-scan base-package="com.mycompany.movies" />
Dieses Tag führt ein automatisches Scannen durch. Angenommen, jede Klasse, die eine Bean werden muss, wird mit einer korrekten Annotation wie @Component
(für einfache Bean) oder @Controller
(für ein Servlet-Steuerelement) oder @Repository
(für DAO
Klassen) versehen, und diese Klassen befinden sich irgendwo unter dem Paket com.mycompany.movies
. Spring findet all diese und erstellt sie eine Bohne für jeden. Dies erfolgt in zwei Scans der Klassen - beim ersten Mal wird nur nach Klassen gesucht, die eine Bean werden müssen, und es werden die Injektionen zugeordnet, die durchgeführt werden müssen, und beim zweiten Scan werden die Beans injiziert. Natürlich können Sie Ihre Beans in der traditionelleren XML-Datei oder mit einer @ Configuration- Klasse (oder einer beliebigen Kombination der drei) definieren.
Die @Autowired
Anmerkung teilt Spring mit, wo eine Injektion erfolgen muss. Wenn Sie es auf eine Methode setzen setMovieFinder
, versteht es (durch das Präfix set
+ die @Autowired
Anmerkung), dass eine Bean injiziert werden muss. Im zweiten Scan sucht Spring nach einer Bean vom Typ MovieFinder
, und wenn es eine solche Bean findet, injiziert es sie dieser Methode. Wenn es zwei solche Bohnen findet, erhalten Sie eine Exception
. Um dies zu vermeiden Exception
, können Sie die @Qualifier
Anmerkung verwenden und ihr auf folgende Weise mitteilen, welche der beiden Bohnen injiziert werden soll:
@Qualifier("redBean")
class Red implements Color {
// Class code here
}
@Qualifier("blueBean")
class Blue implements Color {
// Class code here
}
Oder wenn Sie die Beans lieber in Ihrem XML deklarieren möchten, sieht es ungefähr so aus:
<bean id="redBean" class="com.mycompany.movies.Red"/>
<bean id="blueBean" class="com.mycompany.movies.Blue"/>
In der @Autowired
Deklaration müssen Sie auch die hinzufügen, @Qualifier
um festzustellen, welche der beiden zu injizierenden Farbbohnen:
@Autowired
@Qualifier("redBean")
public void setColor(Color color) {
this.color = color;
}
Wenn Sie nicht zwei Anmerkungen (das @Autowired
und @Qualifier
) verwenden möchten, können Sie @Resource
diese beiden kombinieren:
@Resource(name="redBean")
public void setColor(Color color) {
this.color = color;
}
Das @Resource
(Sie können einige zusätzliche Daten darüber im ersten Kommentar zu dieser Antwort lesen) erspart Ihnen die Verwendung von zwei Anmerkungen und stattdessen nur eine.
Ich werde nur zwei weitere Kommentare hinzufügen:
- Gute Praxis wäre zu verwenden
@Inject
statt , @Autowired
weil es nicht Frühling spezifisch ist und ist Teil des JSR-330
Standard .
- Eine andere gute Praxis wäre, das
@Inject
/ @Autowired
auf einen Konstruktor anstelle einer Methode zu setzen. Wenn Sie es auf einen Konstruktor setzen, können Sie überprüfen, ob die injizierten Beans nicht null sind und schnell fehlschlagen, wenn Sie versuchen, die Anwendung zu starten, und vermeiden, NullPointerException
dass Sie die Bean tatsächlich verwenden müssen.
Update : Um das Bild zu vervollständigen, habe ich eine neue Frage zur @Configuration
Klasse erstellt.
MovieFinder
es sich um eine Schnittstelle handelt und wir eine Bean fürMovieFinderImpl
(bean id = movieFinder) haben, wird Spring diese automatisch nach Typ oder Name injizieren?@Qualifier
. Wenn Sie dies tun - nach Namen, wenn nicht - nach Typ. By-Type würde nur funktionieren, wenn Sie nur eine Bean vom TypMovieFinder
in Ihrem Kontext haben. Mehr als 1 würde zu einer Ausnahme führen.@Autowired
Annotation bei derprepare
Methode in Beispiel 2 funktioniert . Es initialisiert das,MovieRecommender
aber technisch gesehen ist es KEIN Setter.@Autowired
funktioniert auch für Konstrukteure. Es findet die erforderlichen Abhängigkeiten und fügt sie dem Konstruktor ein.Nichts im Beispiel besagt, dass die "Klassen dieselbe Schnittstelle implementieren".
MovieCatalog
ist ein Typ undCustomerPreferenceDao
ist ein anderer Typ. Der Frühling kann sie leicht auseinanderhalten.In Spring 2.x erfolgte die Verkabelung von Beans meist über Bean-IDs oder -Namen. Dies wird von Spring 3.x weiterhin unterstützt, aber häufig haben Sie eine Instanz einer Bean mit einem bestimmten Typ - die meisten Dienste sind Singletons. Das Erstellen von Namen für diese ist mühsam. Also begann Spring, "Autowire nach Typ" zu unterstützen.
Die Beispiele zeigen verschiedene Möglichkeiten, wie Sie Beans in Felder, Methoden und Konstruktoren einfügen können.
Das XML enthält bereits alle Informationen, die Spring benötigt, da Sie in jeder Bean den vollständig qualifizierten Klassennamen angeben müssen. Sie müssen jedoch etwas vorsichtig mit den Schnittstellen sein:
Diese automatische Verdrahtung schlägt fehl:
Da Java die Parameternamen nicht im Bytecode behält, kann Spring die beiden Beans nicht mehr unterscheiden. Das Update ist zu verwenden
@Qualifier
:quelle
prepare
Parameter werden zum Aufrufen dieser Funktion verwendet?@Autowired
Felder eingefügt werden. Spring erkennt dann, dass Parameter benötigt werden, und verwendet dieselben Regeln, die für die Feldinjektion verwendet werden, um die Parameter zu finden.Ja, Sie können die Spring-Servlet-Kontext-XML-Datei so konfigurieren, dass Ihre Beans (dh Klassen) definiert werden, damit sie die automatische Injektion für Sie durchführen kann. Beachten Sie jedoch, dass Sie andere Konfigurationen vornehmen müssen, um Spring zum Laufen zu bringen. Der beste Weg, dies zu tun, besteht darin, einem Tutorial zu folgen.
Sobald Sie Spring wahrscheinlich konfiguriert haben, können Sie in Ihrer XML-Servlet-Kontext-XML-Datei Folgendes ausführen , damit Beispiel 1 oben funktioniert ( ersetzen Sie den Paketnamen von com.movies durch den tatsächlichen Paketnamen und falls dies ein Drittanbieter ist Klasse, dann stellen Sie sicher, dass sich die entsprechende JAR-Datei im Klassenpfad befindet):
oder wenn die MovieFinder-Klasse einen Konstruktor mit einem primitiven Wert hat, könnten Sie so etwas tun:
oder wenn in der MovieFinder-Klasse ein Konstruktor eine andere Klasse erwartet, können Sie Folgendes tun:
... wobei ' otherBeanRef ' eine andere Bean ist, die auf die erwartete Klasse verweist.
quelle
@Autowired