Guide du printemps @Autowired

1. Vue d'ensemble

À partir de Spring 2.5, le framework a introduit l' injection de dépendances basée sur les annotations . L'annotation principale de cette fonctionnalité est @Autowired . Cela permet à Spring de résoudre et d'injecter des beans collaboratifs dans notre bean.

Dans ce didacticiel, nous allons d'abord examiner comment activer le câblage automatique et lediversfaçons d'auto-filer les haricots. Ensuite, nous parlerons de la résolution des conflits de bean à l'aide de l' annotation @Qualifier , ainsi que des scénarios d'exception potentiels.

2. Activation des annotations @Autowired

Le framework Spring permet l'injection automatique de dépendances. En d'autres termes, en déclarant toutes les dépendances de bean dans un fichier de configuration Spring, le conteneur Spring peut gérer automatiquement les relations entre les beans collaborant . C'est ce qu'on appelle l' autowiring Spring Bean .

Pour utiliser la configuration basée sur Java dans notre application, activons l'injection basée sur les annotationspour charger notre configuration Spring:

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

Alternativement, le L'annotation est principalement utilisée pour activer les annotations d'injection de dépendances dans les fichiers XML Spring.

De plus, Spring Boot introduit l' annotation @SpringBootApplication . Cette annotation unique équivaut à utiliser @Configuration , @EnableAutoConfiguration et @ComponentScan .

Utilisons cette annotation dans la classe principale de l'application:

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

En conséquence, lorsque nous exécutons cette application Spring Boot, elle analysera automatiquement les composants du package actuel et de ses sous-packages . Ainsi, il les enregistrera dans le contexte d'application de Spring, et nous permettra d'injecter des beans en utilisant @Autowired .

3. Utilisation de @Autowired

Après avoir activé l'injection d'annotations, nous pouvons utiliser l'autowiring sur les propriétés, les setters et les constructeurs .

3.1. @Autowired sur les propriétés

Voyons comment nous pouvons annoter une propriété à l'aide de @Autowired . Cela élimine le besoin de getters et de setters.

Tout d'abord, définissons un bean fooFormatter :

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

Ensuite, nous injectons ce haricot dans le FooService haricot en utilisant @Autowired sur la définition du champ:

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

Par conséquent, Spring injecte fooFormatter lorsque FooService est créé.

3.2. @Autowired sur Setters

Essayons maintenant d'ajouter l' annotation @Autowired sur une méthode setter.

Dans l'exemple suivant, la méthode setter est appelée avec l'instance de FooFormatter lors de la création de FooService :

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

3.3. @Autowired sur les constructeurs

Enfin, utilisons @Autowired sur un constructeur.

Nous verrons qu'une instance de FooFormatter est injectée par Spring en tant qu'argument du constructeur FooService :

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

4. Dépendances @Autowired et facultatives

Lors de la construction d'un bean, les dépendances @Autowired doivent être disponibles. Sinon, si Spring ne peut pas résoudre un bean pour le câblage, il lèvera une exception .

Par conséquent, il empêche le conteneur Spring de se lancer avec succès à l'exception du formulaire:

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)}

Pour résoudre ce problème, nous devons déclarer un bean du type requis:

public class FooService { @Autowired(required = false) private FooDAO dataAccessor; }

5. Désambiguïsation Autowire

By default, Spring resolves @Autowired entries by type. If more than one bean of the same type is available in the container, the framework will throw a fatal exception.

To resolve this conflict, we need to tell Spring explicitly which bean we want to inject.

5.1. Autowiring by @Qualifier

For instance, let's see how we can use the @Qualifier annotation to indicate the required bean.

First, we'll define 2 beans of type 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"; } }

Now let's try to inject a Formatter bean into the FooService class:

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.