DI est une abréviation pour Dependency Injection, et est souvent traduit par «injection de dépendance» en japonais.
Quand je suis entré en contact avec Spring pour la première fois lorsque j'étais un nouveau diplômé, la première chose qui m'est venue à l'esprit lorsque j'ai entendu ce concept était la marque Hatena. Le lien avec le concept de DI, de conteneur DI et d'annotations au printemps ne m'est pas venu à l'esprit.
Cette fois, pour moi-même quand j'étais débutant, je voudrais résumer brièvement le concept de DI et DI au printemps tout en l'organisant à ma manière.
Je pense qu'il est plus facile de comprendre ce qu'est une dépendance dans le code source.
Main.java
public class Main {
public int hoge() {
var sub = new Sub();
return sub.calculate();
}
}
Dans la méthode hoge de la classe Main, une instance de la classe Sub est créée et utilisée. Lorsqu'il existe une telle classe Main, elle est exprimée comme "La classe principale dépend de la sous-classe".
Je pense qu'il est relativement facile de comprendre les dépendances.
Dans l'exemple précédent, une instance de la classe Sub a été créée en interne, mais la création d'une instance en externe et sa transmission à la classe qui l'utilise s'appelle injection.
Ici, un exemple utilisant un constructeur (injection de constructeur) est montré.
Main.java
public class Main {
private Sub sub;
public int hoge() {
return sub.calculate();
}
//Injection de constructeur
public Main(Sub sub) {
this.sub = sub;
}
}
Auparavant, nous avons créé une instance de la classe Sub dans la méthode hoge, mais dans cet exemple, l'instance est reçue du constructeur.
En faisant cela, lorsque vous utilisez réellement la classe Main,
var sub = new Sub();
var main = new Main(sub);
Sous la forme de, l'instance de la classe Sub est transmise depuis l'extérieur de la classe Main.
Les avantages de ceci seront décrits plus loin.
Lorsque vous entendez le mot conteneur, vous pouvez le considérer comme Docker dans les temps modernes, mais le conteneur dans le conteneur DI est différent du conteneur utilisé dans le contexte de Docker et ainsi de suite.
Si vous l'écrivez en un mot sans crainte de malentendu, le conteneur DI agit comme un "conteneur qui gère l'instance d'injection".
Si vous essayez d'utiliser la classe Main sans utiliser le conteneur DI comme auparavant, vous aurez besoin d'une instance de la classe Sub chaque fois que vous l'utilisez.
Si vous utilisez un conteneur DI, il gérera cette instance, vous n'avez donc pas à créer une instance à chaque fois.
Dans Spring, en spécifiant une classe avec une annotation, vous pouvez spécifier une instance de cette classe comme cible à gérer par le conteneur DI.
Plus précisément, les annotations suivantes.
@Controller
@Service
@Repository
@Bean
En passant, l'instance gérée par le conteneur DI peut être obtenue à l'aide de la méthode getBean de la classe ApplicationContext.
Dans Spring, vous pouvez également définir la portée de la durée pendant laquelle le conteneur DI gère l'instance.
L'étendue qui peut être définie est la suivante et l'annotation Scope est utilisée lors de la définition.
La valeur par défaut de Spring est singleton, mais en modifiant le paramètre, il est possible de détruire et de reconfigurer l'instance gérée par le conteneur, par exemple, en unités de session.
Une chose que les débutants ont tendance à faire est de donner à la classe un champ qui peut changer, malgré le singleton. Un exemple est présenté ci-dessous.
hogeService
@Service
public class hogeService {
private String result;
public int fuga(String suffix) {
result = "test" + suffix;
return result;
}
}
Étant donné que l'annotation de service est ajoutée à hogeService et que la portée n'est pas définie en particulier, la portée est singleton.
En conséquence, vous courez le risque de modifier le champ de résultat dans une autre session, ce qui le rend non sécurisé.
En en faisant une variable au lieu d'un champ de classe comme indiqué ci-dessous, il devient une implémentation thread-safe.
hogeService
@Service
public class hogeService {
public int fuga(String suffix) {
String result = "test" + suffix;
return result;
}
}
Dans Spring, vous pouvez DI en utilisant l'annotation Autowired.
Il existe les trois méthodes d'injection suivantes, y compris l'injection de constructeur mentionnée précédemment.
Plus précisément, chacun est comme ça.
Main.java
public class Main {
//Injection sur le terrain
@Autowired
private Sub sub;
public int hoge() {
return sub.calculate();
}
}
Main.java
public class Main {
private Sub sub;
public int hoge() {
return sub.calculate();
}
//Injection de poseur
@Autowired
public setSub(Sub sub) {
this.sub = sub;
}
}
Main.java
public class Main {
private Sub sub;
public int hoge() {
return sub.calculate();
}
//Injection de constructeur
@Autowired
public Main(Sub sub) {
this.sub = sub;
}
}
En ajoutant l'annotation Autowired, il injectera des instances du conteneur DI dans les arguments des champs, des méthodes et des constructeurs.
D'ailleurs, quand je m'injecte, je l'écris en utilisant l'annotation RequiredArgsConstructor de Lombok dans la bibliothèque, comme décrit dans l'article ici.
Un mérite commun est qu'il facilite l'écriture de tests unitaires, Je pense que cela est vrai.
Voici à nouveau l'exemple du début.
Main.java
public class Main {
public int hoge() {
var sub = new Sub();
return sub.calculate();
}
}
Si la méthode de calcul de cette sous-classe était nécessaire pour accéder à la base de données, le test unitaire de la classe Main serait très difficile.
Cependant, il peut être testé en se moquant des instances injectées par DI. Au fait, j'utilise Mockito lorsque j'utilise une maquette.
Enfin, ce qui suit est un résumé des conteneurs DI et DI en un mot.
DI: Passer une instance d'une classe qui dépend d'une classe de l'extérieur Conteneur DI: un conteneur qui gère l'instance à injecter
Leur utilisation présente l'avantage de faciliter l'écriture des tests et la gestion du périmètre.
C'est tout pour le contenu. Nous espérons que vous trouverez cet article utile. Merci d'avoir lu pour moi jusqu'à la fin.
Documentation officielle Core Technologies
Recommended Posts