Verwendung von Spring @Autowired verstehen

Lesezeit: 7 Minuten

Verwendung von Spring @Autowired verstehen
Neue Abfragen

Ich lese die Referenzdokumentation zu Spring 3.0.x, um die Spring Autowired-Anmerkung zu verstehen:

3.9.2 @Autowired und @Inject

Ich kann die folgenden Beispiele nicht verstehen. Müssen wir etwas im XML tun, damit es funktioniert?

BEISPIEL 1

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Autowired
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...
}

BEISPIEL 2

public class MovieRecommender {

    private MovieCatalog movieCatalog;

    private CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public void prepare(MovieCatalog movieCatalog,
                    CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }

    // ...
}

Wie können die beiden Klassen automatisch verdrahtet werden, indem sie dieselbe Schnittstelle implementieren und dieselbe Klasse verwenden?

Beispiel:

class Red implements Color
class Blue implements Color

class myMainClass{
    @Autowired 
    private Color color;

    draw(){
        color.design(); 
    } 
}

Welche Entwurfsmethode wird aufgerufen? Wie stelle ich sicher, dass die Entwurfsmethode der Red-Klasse aufgerufen wird und nicht Blue?

1646355428 815 Verwendung von Spring @Autowired verstehen
Avi

TL;DR

Die @Autowired Annotation erspart Ihnen die Notwendigkeit, die Verdrahtung in der XML-Datei (oder auf andere Weise) selbst vorzunehmen, und findet für Sie einfach, was wo injiziert werden muss, und erledigt dies für Sie.

Vollständige Erklärung

Die @Autowired Annotation ermöglicht es Ihnen, Konfigurationen an anderer Stelle zu überspringen, was injiziert werden soll, und erledigt dies einfach für Sie. Angenommen, Ihr Paket ist com.mycompany.movies Sie müssen dieses Tag in Ihr XML (Anwendungskontextdatei) einfügen:

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

Dieses Tag führt einen automatischen Scan durch. Angenommen, jede Klasse, die zu einer Bean werden soll, wird mit einer korrekten Annotation wie annotiert @Component (für einfache Bohne) oder @Controller (für ein Servlet-Steuerelement) oder @Repository (zum DAO Klassen) und diese Klassen befinden sich irgendwo unter dem Paket com.mycompany.movies, Spring wird all diese finden und für jeden eine Bohne erstellen. Dies geschieht in 2 Scans der Klassen – beim ersten Mal sucht es nur nach Klassen, die zu einer Bohne werden müssen, und ordnet die Injektionen zu, die es tun muss, und beim zweiten Scan injiziert es die Bohnen. Natürlich können Sie Ihre Beans in der traditionelleren XML-Datei oder mit einer definieren @Configuration Klasse (oder eine beliebige Kombination der drei).

Die @Autowired Annotation teilt Spring mit, wo eine Injektion erfolgen muss. Wenn Sie es auf eine Methode setzen setMovieFinder es versteht (durch das Präfix set + die @Autowired Anmerkung), dass eine Bohne injiziert werden muss. Beim zweiten Scan sucht Spring nach einem Bean-Typ MovieFinder, und wenn es eine solche Bohne findet, injiziert es sie in diese Methode. Wenn es zwei solche Bohnen findet, erhalten Sie eine Exception. Um das zu vermeiden Exceptiondu kannst den … benutzen @Qualifier Anmerkung und teilen Sie ihm auf folgende Weise mit, 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 es vorziehen, die Beans in Ihrem XML zu deklarieren, würde es ungefähr so ​​​​aussehen:

<bean id="redBean" class="com.mycompany.movies.Red"/>

<bean id="blueBean" class="com.mycompany.movies.Blue"/>

In dem @Autowired Deklaration müssen Sie auch die hinzufügen @Qualifier um zu sagen, welche der beiden Farbbohnen zu injizieren ist:

@Autowired
@Qualifier("redBean")
public void setColor(Color color) {
  this.color = color;
}

Wenn Sie nicht zwei Anmerkungen verwenden möchten (die @Autowired und @Qualifier) können Sie verwenden @Resource um diese beiden zu kombinieren:

@Resource(name="redBean")
public void setColor(Color color) {
  this.color = color;
}

Die @Resource (Sie können einige zusätzliche Daten dazu im ersten Kommentar zu dieser Antwort lesen) erspart Ihnen die Verwendung von zwei Anmerkungen und verwendet stattdessen nur eine.

Ich füge nur zwei weitere Kommentare hinzu:

  1. Eine gute Praxis wäre zu verwenden @Inject anstatt @Autowired weil es nicht Spring-spezifisch ist und ist Teil von JSR-330 Standard.
  2. Eine weitere gute Praxis wäre, die zu setzen @Inject / @Autowired auf einen Konstruktor statt auf eine Methode. 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 a vermeiden NullPointerException wenn Sie die Bohne tatsächlich verwenden müssen.

Aktualisieren: Um das Bild zu vervollständigen, habe ich eine neue Frage dazu erstellt @Configuration Klasse.

  • Nur um Ihre großartige Antwort zu vervollständigen: ‘@Resource’ ist Teil des JSR-250-Standards und hat eine zusätzliche Semantik über die einfache Injektion hinaus (Wie Sie gesagt haben, stammt ‘@Autowired’ von Spring; und ‘@Inject’ ist Teil von JSR-330) 🙂

    – Ignacio Rubio

    1. September 2014 um 15:12 Uhr

  • Wenn MovieFinder ist eine Schnittstelle, und wir haben eine Bohne für MovieFinderImpl(bean id = movieFinder), Spring wird es automatisch nach Typ oder Name einfügen?

    – JaskeyLam

    8. August 2015 um 12:37 Uhr

  • @jaskey – es hängt davon ab, ob Sie verwenden @Qualifier. Wenn ja – nach Namen, wenn nicht – nach Typ. By-type würde nur funktionieren, wenn Sie nur eine Bean vom Typ haben MovieFinder in deinem Kontext. Mehr als 1 würde zu einer Ausnahme führen.

    – Avi

    8. August 2015 um 17:07 Uhr

  • @Avi, tolle Antwort. Aber ich verstehe nicht, wie das @Autowired Anmerkung funktioniert auf der prepare Methode ein Beispiel 2. Es initialisiert die MovieRecommender aber technisch gesehen ist es so NICHT ein Setzer.

    – Karan Chadha

    28. Februar 2017 um 9:26 Uhr


  • @KaranChadha – Das @Autowired funktioniert auch für Konstrukteure. Es findet die erforderlichen Abhängigkeiten und injiziert sie in den Konstruktor.

    – Avi

    28. Februar 2017 um 9:59 Uhr

1646355428 237 Verwendung von Spring @Autowired verstehen
Aaron Digulla

Nichts im Beispiel besagt, dass die “Klassen dieselbe Schnittstelle implementieren”. MovieCatalog ist ein Typ und CustomerPreferenceDao ist ein anderer Typ. Der Frühling kann sie leicht voneinander unterscheiden.

In Spring 2.x erfolgte die Verknüpfung von Beans meist über Bean-IDs oder -Namen. Dies wird immer noch von Spring 3.x unterstützt, aber oft 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 by type” zu unterstützen.

Was die Beispiele zeigen, sind 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 vollqualifizierten Klassennamen angeben müssen. Bei Schnittstellen muss man allerdings etwas aufpassen:

Diese automatische Verdrahtung wird fehlschlagen:

 @Autowired
 public void prepare( Interface1 bean1, Interface1 bean2 ) { ... }

Da Java die Parameternamen nicht im Bytecode hält, kann Spring nicht mehr zwischen den beiden Beans unterscheiden. Die Lösung ist zu verwenden @Qualifier:

 @Autowired
 public void prepare( @Qualifier("bean1") Interface1 bean1,
     @Qualifier("bean2")  Interface1 bean2 ) { ... }

  • @AaronDigulla Das war schön. Ich möchte jedoch wissen, wie Sie die Funktion aufrufen preparewelche Parameter werden verwendet, um diese Funktion aufzurufen?

    – Nguyen Quang Anh

    10. Juli 2017 um 2:04 Uhr

  • @NguyenQuangAnh Ich rufe die Methode nicht auf, Spring wird es tun, wenn die Bean erstellt wird. Das passiert genau wann @Autowired Felder injiziert 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.

    – Aaron Digulla

    4. September 2017 um 11:53 Uhr

Ja, Sie können die Spring-Servlet-Kontext-XML-Datei konfigurieren, um Ihre Beans (dh Klassen) zu definieren, damit sie die automatische Injektion für Sie übernehmen kann. Beachten Sie jedoch, dass Sie andere Konfigurationen vornehmen müssen, um Spring zum Laufen zu bringen, und der beste Weg, dies zu tun, besteht darin, einem Tutorial von Grund auf zu folgen.

Sobald Sie Ihr Spring wahrscheinlich konfiguriert haben, können Sie Folgendes in Ihrer Spring-Servlet-Kontext-XML-Datei tun, damit Beispiel 1 oben funktioniert (bitte ersetzen der Paketname von com.filme wie der wahre Paketname lautet und wenn es sich um eine Klasse eines Drittanbieters handelt, stellen Sie sicher, dass sich die entsprechende JAR-Datei im Klassenpfad befindet):

<beans:bean id="movieFinder" class="com.movies.MovieFinder" />

oder wenn die MovieFinder-Klasse einen Konstruktor mit einem primitiven Wert hat, dann könnten Sie so etwas tun:

<beans:bean id="movieFinder" class="com.movies.MovieFinder" >
    <beans:constructor-arg value="100" />
</beans:bean>

oder wenn die MovieFinder-Klasse einen Konstruktor hat, der eine andere Klasse erwartet, könnten Sie so etwas tun:

<beans:bean id="movieFinder" class="com.movies.MovieFinder" >
    <beans:constructor-arg ref="otherBeanRef" />
</beans:bean>

…wo ‘andereBeanRef‘ ist eine weitere Bean, die einen Verweis auf die erwartete Klasse hat.

  • Das Definieren der gesamten Verkabelung im XML verfehlt einfach die ganze Idee von @Autowired

    – Avi

    17. Oktober 2013 um 6:51 Uhr

929260cookie-checkVerwendung von Spring @Autowired verstehen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy