it-swarm.com.de

Grundlegendes zur Verwendung von Spring @Autowired

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

.9.2 @Autowired und @Inject

Ich kann die folgenden Beispiele nicht verstehen. Müssen wir etwas in 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 verkabelt werden, indem dieselbe Schnittstelle implementiert und dieselbe Klasse verwendet wird?

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 Klasse Rot und nicht Blau aufgerufen wird?

287
NewQueries

TL; DR

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

Vollständige Erklärung

Mit der Annotation @Autowired können Sie Konfigurationen an anderer Stelle der zu injizierenden Elemente überspringen und dies nur für Sie tun. Angenommen, Ihr Paket ist com.mycompany.movies, müssen Sie dieses Tag in Ihre XML-Datei (Anwendungskontextdatei) einfügen:

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

Dieses Tag führt einen automatischen Scan durch. Angenommen, jede Klasse, die eine Bean werden soll, wird mit einer korrekten Annotation wie @Component (für eine einfache Bean) oder @Controller (für ein Servlet-Steuerelement) oder @Repository (für DAO Klassen) und diese Klassen befinden sich irgendwo unter dem Paket com.mycompany.movies, Spring findet alle diese und erstellt für jede eine Bean. Dies geschieht in zwei Durchläufen der Klassen - das erste Mal wird nur nach Klassen gesucht, die zu einer Bean werden müssen, und die durchzuführenden Injektionen werden zugeordnet, und beim zweiten Durchlauf 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 Anmerkung @Autowired teilt Spring mit, wo eine Injektion erfolgen muss. Wenn Sie es auf eine Methode setMovieFinder setzen, versteht es (unter dem Präfix set + der Anmerkung @Autowired), dass eine Bohne injiziert werden muss. Im zweiten Scan sucht Spring nach einer Bean des Typs MovieFinder. Wenn eine solche Bean gefunden wird, wird sie dieser Methode hinzugefügt. Wenn es zwei solcher Bohnen findet, erhalten Sie ein Exception. Um das Exception zu vermeiden, können Sie die Annotation @Qualifier verwenden und ihr mitteilen, welche der beiden Bohnen auf folgende Weise 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 dies ungefähr so ​​aussehen:

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

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

In der @Autowired -Deklaration müssen Sie auch den @Qualifier hinzufügen, um zu bestimmen, welche der beiden Farbbohnen injiziert werden sollen:

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

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

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

Der @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 Sie verwenden stattdessen nur eine.

Ich werde nur zwei weitere Kommentare hinzufügen:

  1. Es empfiehlt sich, @Inject anstelle von @Autowired zu verwenden, da dies nicht frühlingsspezifisch ist und Teil des Standards JSR-330 ist.
  2. Eine weitere bewährte Methode wäre, den @Inject/@Autowired anstelle einer Methode in einen Konstruktor einzufügen. Wenn Sie es in einem Konstruktor ablegen, können Sie überprüfen, ob die injizierten Beans nicht null sind, und beim Versuch, die Anwendung zu starten, schnell fehlschlagen. Außerdem können Sie ein NullPointerException vermeiden, wenn Sie die Bean tatsächlich verwenden müssen.

Update : Um das Bild zu vervollständigen, habe ich eine neue Frage über die Klasse @Configuration erstellt.

521
Avi

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 unterscheiden.

Im Frühjahr 2.x erfolgte die Verkabelung der Beans meist über Bean-IDs oder -Namen. Dies wird immer noch von Spring 3.x unterstützt, aber häufig haben Sie eine Instanz einer Bean mit einem bestimmten Typ - die meisten Services sind Singletons. Es ist mühsam, Namen für diese zu erstellen. Also fing Spring an, "autowire by type" zu unterstützen.

Die Beispiele zeigen verschiedene Möglichkeiten, wie Sie Beans in Felder, Methoden und Konstruktoren einfügen können.

Die XML enthält bereits alle Informationen, die Spring benötigt, da Sie in jeder Bean den vollständig qualifizierten Klassennamen angeben müssen. Mit Schnittstellen muss man allerdings etwas vorsichtig sein:

Diese automatische Verdrahtung schlägt fehl:

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

Da Java die Parameternamen nicht im Bytecode behält, kann Spring die beiden Beans nicht mehr unterscheiden. Das Update besteht darin, @Qualifier zu verwenden:

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

Ja, Sie können die Spring-Servlet-Kontext-XML-Datei so konfigurieren, dass sie Ihre Beans (d. H. Klassen) definiert, sodass die automatische Injektion für Sie durchgeführt werden kann. Beachten Sie jedoch, dass Sie andere Konfigurationen vornehmen müssen, damit Spring ausgeführt werden kann. Der beste Weg, dies zu tun, besteht darin, einem Tutorial zu folgen.

Sobald Sie Ihren Spring konfiguriert haben, können Sie wahrscheinlich Folgendes in Ihrer Spring-Servlet-Kontext-XML-Datei ausführen, damit Beispiel 1 funktioniert (bitte ersetzen Sie den Paketnamen of com.movies Wie lautet der wahre Paketname und wenn dies eine Klasse von Drittanbietern ist, 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, 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, dann könnten Sie so etwas tun,

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

... wobei ' otherBeanRef ' eine weitere Bean ist, die einen Verweis auf die erwartete Klasse enthält.

5
Cem Sultan