Guide to Spring @Autowired

Anleitung zu Spring @Autowired

1. Überblick

Beginnend mit Spring 2.5 führte das Framework einen neuen Stil der Abhängigkeitsinjektion ein, der von@Autowired Annotations gesteuert wird. Mit dieser Annotation kann Spring zusammenarbeitende Beans auflösen und in Ihre Bean einfügen.

In diesem Tutorial werden wir uns ansehen, wie Sie die verschiedenen ways to wire in beans,_ making beans optional, resolving bean conflicts using _@Qualifier Annotationen für das automatische Verdrahten von, sowie mögliche Ausnahmeszenarien aktivieren.

Weitere Lektüre:

Scannen von Federkomponenten

Erfahren Sie mehr über den Mechanismus beim Scannen von Spring-Komponenten und wie Sie ihn an Ihre eigenen Bedürfnisse anpassen können

Read more

Einführung in die Inversion von Control und Dependency Injection mit Spring

Eine kurze Einführung in die Konzepte von Inversion of Control und Dependency Injection, gefolgt von einer einfachen Demonstration mit dem Spring Framework

Read more

2. Aktivieren von@Autowired Annotations

Wenn Sie in Ihrer Anwendung eine Java-basierte Konfiguration verwenden, können Sie die annotationsgesteuerte Injektion aktivieren, indem SieAnnotationConfigApplicationContext verwenden, um Ihre Federkonfiguration wie folgt zu laden:

@Configuration
@ComponentScan("com.example.autowire.sample")
public class AppConfig {}

Alternativ kann es in Spring XML aktiviert werden, indem es in Spring XML-Dateien wie folgt deklariert wird:<context:annotation-config/>

3. Verwenden von@Autowired

Sobald die Anmerkungsinjektion aktiviert ist, kann die automatische Verdrahtung für Eigenschaften, Setter und Konstruktoren verwendet werden.

3.1. @Autowired auf Eigenschaften

Die Annotation kann direkt auf Eigenschaften angewendet werden, sodass keine Getter und Setter mehr erforderlich sind:

@Component("fooFormatter")
public class FooFormatter {

    public String format() {
        return "foo";
    }
}
@Component
public class FooService {

    @Autowired
    private FooFormatter fooFormatter;

}

Im obigen Beispiel sucht Spring nachfooFormatter und injiziert sie, wennFooService erstellt wird.

3.2. @Autowired auf Setter

Die Annotation@Autowired kann für Setter-Methoden verwendet werden. Wenn im folgenden Beispiel die Annotation für die Setter-Methode verwendet wird, wird die Setter-Methode mit der InstanzFooFormatter aufgerufen, wennFooService erstellt wird:

public class FooService {

    private FooFormatter fooFormatter;

    @Autowired
    public void setFooFormatter(FooFormatter fooFormatter) {
            this.fooFormatter = fooFormatter;
    }
}

3.3. @Autowired auf Konstruktoren

Die Annotation@Autowired kann auch für Konstruktoren verwendet werden. Wenn im folgenden Beispiel die Annotation für einen Konstruktor verwendet wird, wird dem Konstruktor eine Instanz vonFooFormatter als Argument eingefügt, wennFooService erstellt wird:

public class FooService {

    private FooFormatter fooFormatter;

    @Autowired
    public FooService(FooFormatter fooFormatter) {
        this.fooFormatter = fooFormatter;
    }
}

4. @Autowired und optionale Abhängigkeiten

Spring erwartet, dass@Autowired Abhängigkeiten verfügbar sind, wenn die abhängige Bean erstellt wird. Wenn das Framework eine Bean für die Verkabelung nicht auflösen kann, wird die unten angegebene Ausnahme ausgelöst und verhindert, dass der Spring-Container erfolgreich gestartet wird:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.autowire.sample.FooDAO] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency.
Dependency annotations:
{@org.springframework.beans.factory.annotation.Autowired(required=true)}

Um dies zu vermeiden, kann eine Bean optional wie folgt angegeben werden:

public class FooService {

    @Autowired(required = false)
    private FooDAO dataAccessor;

}

5. Autowire-Disambiguierung

Standardmäßig löst Spring@Autowired Einträge nach Typ auf. Wenn mehr als ein Bean desselben Typs im Container verfügbar ist, gibt das Framework eine schwerwiegende Ausnahme aus, die darauf hinweist, dass mehr als ein Bean für die automatische Verdrahtung verfügbar ist.

5.1. Autodraht um@Qualifier

Die Annotation@Qualifier kann verwendet werden, um auf die erforderliche Bean hinzuweisen und sie einzugrenzen:

@Component("fooFormatter")
public class FooFormatter implements Formatter {

    public String format() {
        return "foo";
    }
}
@Component("barFormatter")
public class BarFormatter implements Formatter {

    public String format() {
        return "bar";
    }
}
public class FooService {

    @Autowired
    private Formatter formatter;

}

Da für den Spring-Container zwei konkrete Implementierungen vonFormatter zum Injizieren verfügbar sind, löst Spring beim Erstellen derFooService eineNoUniqueBeanDefinitionException-Ausnahme aus: __

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [com.autowire.sample.Formatter] is defined:
expected single matching bean but found 2: barFormatter,fooFormatter

Dies kann vermieden werden, indem die Implementierung mit einer@Qualifier-Annotation eingegrenzt wird:

public class FooService {

    @Autowired
    @Qualifier("fooFormatter")
    private Formatter formatter;

}

Durch Angabe von@Qualifier mit dem Namen der spezifischen Implementierung, in diesem Fall alsfooFormatter, können Mehrdeutigkeiten vermieden werden, wenn Spring mehrere Beans desselben Typs findet.

Bitte beachten Sie, dass der Wert der Annotation@Qualifiermit dem Namen übereinstimmt, der in der Annotation@Componentunserer ImplementierungFooFormatterdeklariert ist.

5.2. Autowiring von Custom Qualifier

Mit Spring können wir unsere eigene@Qualifier-Anmerkung erstellen. Um ein benutzerdefiniertes Qualifikationsmerkmal zu erstellen, definieren Sie eine Annotation und geben Sie die Annotation@Qualifierin der Definition wie folgt an:

@Qualifier
@Target({
  ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface FormatterType {

    String value();

}

Nach der Definition kannFormatterType in verschiedenen Implementierungen verwendet werden, um einen benutzerdefinierten Wert anzugeben:

@FormatterType("Foo")
@Component
public class FooFormatter implements Formatter {

    public String format() {
        return "foo";
    }
}
@FormatterType("Bar")
@Component
public class BarFormatter implements Formatter {

    public String format() {
        return "bar";
    }
}

Sobald die Implementierungen mit Anmerkungen versehen sind, kann die benutzerdefinierte Qualifier-Anmerkung wie folgt verwendet werden:

@Component
public class FooService {

    @Autowired
    @FormatterType("Foo")
    private Formatter formatter;

}

Der in der Annotation@Targetangegebene Wert schränkt ein, wo das Qualifikationsmerkmal zum Markieren von Injektionspunkten verwendet werden kann.

Im obigen Code-Snippet kann das Qualifikationsmerkmal verwendet werden, um den Punkt zu disambiguieren, an dem Spring die Bean in ein Feld, eine Methode, einen Typ und einen Parameter injizieren kann.

5.3. Autowiring nach Namen

Als Fallback verwendet Spring den Bean-Namen als Standardqualifikationswert.

Wenn Sie also den Namen der Bean-Eigenschaft definieren, stimmt Spring in diesem Fall alsfooFormatter, mit der Implementierung vonFooFormatterüberein und fügt diese spezifische Implementierung ein, wennFooService erstellt wird:

public class FooService {

    @Autowired
    private Formatter fooFormatter;

}

6. Fazit

Obwohl sowohl@Qualifier als auch die Beanback-Übereinstimmung von Bean-Namen verwendet werden können, um auf eine bestimmte Bean einzugrenzen, dreht sich beim Autowiring alles um die Injektion nach Typ, und so kann diese Container-Funktion am besten verwendet werden.

Der Quellcode dieses Tutorials befindet sich inthe GitHub project - dies ist ein Eclipse-basiertes Projekt, daher sollte es einfach zu importieren und auszuführen sein.