1
votes

Quel est le but du marquage d'un constructeur d'injection avec un attribut @Autowired?

J'essaie de comprendre l'annotation @Autowired. Je l'ai lu, mais cela n'a toujours pas beaucoup de sens pour moi

​​Le cas spécifique que je recherche est de passer un référentiel dans une classe de micro-service

Pourquoi le faisons-nous

public SomeClass (Repo repo) {
    this.repo = repo;
}

au lieu de simplement faire

@Autowired
public SomeClass (Repo repo) {
    this.repo = repo;
}


0 commentaires

4 Réponses :


0
votes

Lorsque vous avez plusieurs constructeurs, vous devez indiquer à spring quel constructeur utiliser. Inutile la plupart du temps.

Vérifiez ici: https://www.baeldung.com/constructor-injection- au printemps

Depuis le printemps 4.3, les classes avec un seul constructeur peuvent omettre Annotation @Autowired. Un petit peu de commodité et retrait passe-partout!


1 commentaires

Il n'y a qu'un seul constructeur dans la classe que je regarde



1
votes

Vous avez raison. Les conteneurs DI, comme Spring, sont destinés à découpler les composants les uns des autres, en adhérant au Principe d'inversion de dépendance (DIP). De ce point de vue, il est plutôt gênant - c'est le moins qu'on puisse dire - que votre conteneur DI vous oblige à appliquer ces attributs spécifiques à la bibliothèque à vos classes. Cela introduit à nouveau un couplage serré - ce que nous travaillons si dur pour éviter. Cela force également un verrouillage du fournisseur. Tout votre code d'application dépend désormais de cet outil externe. Ceci est une violation du DIP.

À la place, lorsque vos composants d'application ont un constructeur public unique , qui est une bonne pratique , il ne devrait pas être nécessaire de définir un tel attribut sur la classe. Dans ce cas, le constructeur de la classe déclare sans ambiguïté ses dépendances requises. Tout bon conteneur DI devrait être capable de composer un graphe d'objets basé sur les informations de type statique fournies par ce constructeur unique.

Si je ne me trompe pas, les nouvelles versions de Spring vous permettent d'omettre l'attribut.


0 commentaires

1
votes

Vous pouvez faire ceci:

public SomeClass (Repo repo) {
    this.repo = repo;
}

si vous prévoyez d'instancier votre objet vous-même. Mais puisque vous voulez que le conteneur instancie vos objets (beans), vous lui demandez d'injecter votre dépendance Repo lors de la création du bean SomeClass . Vous faites cela en ajoutant @Autowired au-dessus de votre constructeur.

Vous pouvez également faire ceci (injection de champ):

@Component
@RequiredArgConstructor
public class SomeClass {

    private final Repo repo;
}

Mais pour faciliter les tests unitaires, l'injection de constructeur est préférable. Notez que depuis le printemps 4.3, @Autowired n'est plus nécessaire sur le constructeur.

EDIT

Mieux, lorsque vous utilisez Lombok vous pouvez faire ceci:

@Component
public class SomeClass {
    @Autowired
    private Repo repo;
} 

Lombok générera le constructeur

public SomeClass (Repo repo) {
    this.repo = repo;
}

pour vous et le container va injecter la dépendance.


2 commentaires

Mais nous avons une classe de test qui instancie explicitement la classe Repo, puis passe l'objet Repo dans la classe Micro-Service ("SomeClass"). Est-ce donc incorrect?


Cela dépend du type de test que vous effectuez. Pour le test unitaire, ce n'est pas correct, vous devez vous moquer de la dépendance repo . Pour le test d'intégration, cela peut être correct, mais puisque vous utilisez Spring, laissez Spring gérer votre dépendance (sauf pour les tests unitaires).



0
votes

L'annotation @Autowired utilisera automatiquement un 'Bean' (ressource gérée par spring) de type Repo à partir du contexte d'application s'il en existe un. Si votre méthode SomeClass est elle-même un 'Bean' (annoté avec @Component, @Service ou @Repository), spring s'assurera qu'un bean de type Repo existe dans le contexte de l'application avant d'instancier votre bean SomeClass.

Cet article est utile: https://www.baeldung.com/spring-autowire

Comme d'autres sur ce fil l'ont mentionné, l'injection de constructeur facilite les tests unitaires. Une façon de contourner ce problème est de créer une classe statique annotée avec @TestConfiguration qui contient les beans dont vous avez besoin pour votre contexte de test.

Cet article contient quelques informations à ce sujet: https://www.baeldung.com/spring -boot-testing

Le site Baeldung est une excellente ressource si vous êtes nouveau au printemps.


0 commentaires