Leitfaden für Spring @Autowired

1. Übersicht

Ab Spring 2.5 führte das Framework eine durch Anmerkungen gesteuerte Abhängigkeitsinjektion ein . Die Hauptanmerkung dieser Funktion lautet @Autowired . Dadurch kann Spring kollaborierende Bohnen auflösen und in unsere Bohnen injizieren.

In diesem Tutorial sehen wir uns zunächst an, wie das automatische Verdrahten aktiviert wirdverschiedeneMöglichkeiten, Bohnen automatisch zu verdrahten. Anschließend werden wir uns mit der Lösung von Bean-Konflikten mithilfe der Annotation @Qualifier sowie mit möglichen Ausnahmeszenarien befassen .

2. Aktivieren von @Autowired Annotations

Das Spring-Framework ermöglicht die automatische Abhängigkeitsinjektion. Mit anderen Worten, durch Deklarieren aller Bean-Abhängigkeiten in einer Spring-Konfigurationsdatei kann der Spring-Container automatisch Beziehungen zwischen zusammenarbeitenden Beans verdrahten . Dies wird als Spring Bean Autowiring bezeichnet .

Um die Java-basierte Konfiguration in unserer Anwendung zu verwenden, aktivieren wir die annotationsgesteuerte InjektionSo laden Sie unsere Federkonfiguration:

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

Alternativ kann die Annotation wird hauptsächlich verwendet, um die Annotationen zur Abhängigkeitsinjektion in Spring XML-Dateien zu aktivieren.

Darüber hinaus führt Spring Boot die Annotation @SpringBootApplication ein . Diese einzelne Anmerkung entspricht der Verwendung von @Configuration , @EnableAutoConfiguration und @ComponentScan .

Verwenden wir diese Anmerkung in der Hauptklasse der Anwendung:

@SpringBootApplication class VehicleFactoryApplication { public static void main(String[] args) { SpringApplication.run(VehicleFactoryApplication.class, args); } }

Wenn wir diese Spring Boot-Anwendung ausführen, werden daher die Komponenten im aktuellen Paket und seinen Unterpaketen automatisch gescannt . Auf diese Weise werden sie im Anwendungskontext von Spring registriert und wir können Beans mit @Autowired injizieren .

3. Verwenden von @Autowired

Nach dem Aktivieren der Anmerkungsinjektion können wir Autowiring für Eigenschaften, Setter und Konstruktoren verwenden .

3.1. @Autowired auf Eigenschaften

Mal sehen, wie wir eine Eigenschaft mit @Autowired mit Anmerkungen versehen können . Dies macht Getter und Setter überflüssig.

Definieren wir zunächst eine fooFormatter- Bean:

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

Dann fügen wir diese Bean mit @Autowired in der Felddefinition in die FooService- Bean ein :

@Component public class FooService { @Autowired private FooFormatter fooFormatter; }

Infolgedessen injiziert Spring fooFormatter, wenn FooService erstellt wird.

3.2. @Autowired auf Setter

Versuchen wir nun, einer Setter-Methode eine @ Autowired- Annotation hinzuzufügen .

Im folgenden Beispiel wird die Setter-Methode mit der Instanz von FooFormatter aufgerufen, wenn FooService erstellt wird:

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

3.3. @Autowired auf Konstruktoren

Verwenden wir abschließend @Autowired für einen Konstruktor.

Wir werden sehen, dass eine Instanz von FooFormatter von Spring als Argument für den FooService- Konstruktor eingefügt wird :

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

4. @Autowired und optionale Abhängigkeiten

Wenn eine Bean erstellt wird, sollten die @ Autowired- Abhängigkeiten verfügbar sein. Andernfalls löst Spring eine Ausnahme aus , wenn Spring eine Bean nicht für die Verkabelung auflösen kann .

Folglich wird verhindert, dass der Spring-Container mit Ausnahme des Formulars 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 beheben, müssen wir eine Bean des erforderlichen Typs deklarieren:

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 eine Bean desselben Typs im Container verfügbar ist, löst das Framework eine schwerwiegende Ausnahme aus .

Um diesen Konflikt zu lösen, müssen wir Spring explizit mitteilen, welche Bean wir injizieren möchten.

5.1. Autowiring von @Qualifier

Lassen Sie uns zum Beispiel sehen, wie wir die Annotation @Qualifier verwenden können , um die erforderliche Bean anzugeben.

Zuerst definieren wir 2 Beans vom Typ Formatter :

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

Versuchen wir nun, eine Formatter- Bean in die FooService- Klasse einzufügen :

public class FooService { @Autowired private Formatter formatter; }

In our example, there are two concrete implementations of Formatter available for the Spring container. As a result, Spring will throw a NoUniqueBeanDefinitionException exception when constructing the FooService:

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 

We can avoid this by narrowing the implementation using a @Qualifier annotation:

public class FooService { @Autowired @Qualifier("fooFormatter") private Formatter formatter; }

When there are multiple beans of the same type, it's a good idea to use @Qualifier to avoid ambiguity.

Please note that the value of the @Qualifier annotation matches with the name declared in the @Component annotation of our FooFormatter implementation.

5.2. Autowiring by Custom Qualifier

Spring also allows us to create our own custom @Qualifier annotation. To do so, we should provide the @Qualifier annotation with the definition:

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

Then we can use the FormatterType within various implementations to specify a custom value:

@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"; } }

Finally, our custom Qualifier annotation is ready to use for autowiring:

@Component public class FooService { @Autowired @FormatterType("Foo") private Formatter formatter; } 

The value specified in the @Target meta-annotation restricts where to apply the qualifier, which in our example is fields, methods, types, and parameters.

5.3. Autowiring by Name

Spring uses the bean's name as a default qualifier value. It will inspect the container and look for a bean with the exact name as the property to autowire it.

Hence, in our example, Spring matches the fooFormatter property name to the FooFormatter implementation. Therefore, it injects that specific implementation when constructing FooService:

public class FooService { @Autowired private Formatter fooFormatter; }

6. Conclusion

In this article, we discussed autowiring and the different ways to use it. We also examined ways to solve two common autowiring exceptions caused by either a missing bean or an ambiguous bean injection.

The source code of this article is available on the GitHub project.