DI ist eine Abkürzung für Dependency Injection und wird im Japanischen häufig als "Dependency Injection" übersetzt.
Als ich als neuer Absolvent zum ersten Mal von diesem Konzept erfuhr, kam mir das Hatena-Zeichen in den Sinn. Der Zusammenhang mit dem Konzept von DI, DI-Container und Anmerkungen im Frühjahr kam mir nicht in den Sinn.
Dieses Mal möchte ich als Anfänger das Konzept von DI und DI im Frühjahr kurz zusammenfassen und es auf meine eigene Weise organisieren.
Ich denke, es ist einfacher zu verstehen, was eine Abhängigkeit im Quellcode ist.
Main.java
public class Main {
public int hoge() {
var sub = new Sub();
return sub.calculate();
}
}
In der hoge-Methode der Main-Klasse wird eine Instanz der Sub-Klasse erstellt und verwendet. Wenn es eine solche Hauptklasse gibt, wird sie als "Hauptklasse hängt von Unterklasse ab" ausgedrückt.
Ich denke, es ist relativ einfach, Abhängigkeiten zu verstehen.
Im vorherigen Beispiel wurde eine Instanz der Sub-Klasse intern erstellt. Eine externe Instanz zu erstellen und an die Klasse zu übergeben, die sie verwendet, wird als Injection bezeichnet.
Hier wird ein Beispiel mit einem Konstruktor (Konstruktorinjektion) gezeigt.
Main.java
public class Main {
private Sub sub;
public int hoge() {
return sub.calculate();
}
//Konstruktorinjektion
public Main(Sub sub) {
this.sub = sub;
}
}
Früher haben wir eine Instanz der Sub-Klasse in der hoge-Methode erstellt, aber in diesem Beispiel wird die Instanz vom Konstruktor empfangen.
Wenn Sie auf diese Weise tatsächlich die Hauptklasse verwenden,
var sub = new Sub();
var main = new Main(sub);
In Form von wird die Instanz der Unterklasse von außerhalb der Hauptklasse übergeben.
Die Vorteile davon werden später beschrieben.
Wenn Sie das Wort Container hören, können Sie es in der heutigen Zeit als Docker betrachten, aber der Container im DI-Container unterscheidet sich von dem Container, der im Kontext von Docker usw. verwendet wird.
Wenn Sie es ohne Angst vor Missverständnissen in einem Wort schreiben, fungiert der DI-Container als "Container, der die injizierende Instanz verwaltet".
Wenn Sie versuchen, die Hauptklasse zu verwenden, ohne den DI-Container wie zuvor zu verwenden, benötigen Sie bei jeder Verwendung eine Instanz der Unterklasse.
Wenn Sie einen DI-Container verwenden, wird diese Instanz verwaltet, sodass Sie nicht jedes Mal eine Instanz erstellen müssen.
In Spring können Sie durch Angabe einer Klasse mit einer Anmerkung eine Instanz dieser Klasse als Ziel angeben, das vom DI-Container verwaltet werden soll.
Insbesondere die folgenden Anmerkungen.
@Controller
@Service
@Repository
@Bean
Die vom DI-Container verwaltete Instanz kann übrigens mithilfe der getBean-Methode der ApplicationContext-Klasse abgerufen werden.
In Spring können Sie auch festlegen, wie lange der DI-Container die Instanz verwaltet.
Der Bereich kann wie folgt festgelegt werden, und die Bereichsanmerkung wird beim Festlegen verwendet.
Die Standardeinstellung von Spring ist Singleton. Durch Ändern der Einstellung ist es jedoch möglich, die vom Container verwaltete Instanz zu zerstören und neu zu konfigurieren, z. B. in Sitzungseinheiten.
Eine Sache, die Anfänger tun, ist, der Klasse ein Feld zu geben, das sich trotz des Singleton ändern kann. Ein Beispiel ist unten gezeigt.
hogeService
@Service
public class hogeService {
private String result;
public int fuga(String suffix) {
result = "test" + suffix;
return result;
}
}
Da die Service-Annotation zu hogeService hinzugefügt wird und der Bereich nicht speziell festgelegt ist, ist der Bereich Singleton.
Infolgedessen besteht das Risiko, dass Sie das Ergebnisfeld in einer anderen Sitzung ändern, wodurch es nicht mit dem Gewinde versehen ist.
Indem Sie es wie unten gezeigt zu einer Variablen anstelle eines Klassenfelds machen, wird es zu einer thread-sicheren Implementierung.
hogeService
@Service
public class hogeService {
public int fuga(String suffix) {
String result = "test" + suffix;
return result;
}
}
Im Frühjahr können Sie mithilfe der Annotation Autowired DI erstellen.
Es gibt die folgenden drei Injektionsmethoden, einschließlich der zuvor erwähnten Konstruktorinjektion.
Insbesondere ist jeder so.
Main.java
public class Main {
//Feldinjektion
@Autowired
private Sub sub;
public int hoge() {
return sub.calculate();
}
}
Main.java
public class Main {
private Sub sub;
public int hoge() {
return sub.calculate();
}
//Setter-Injektion
@Autowired
public setSub(Sub sub) {
this.sub = sub;
}
}
Main.java
public class Main {
private Sub sub;
public int hoge() {
return sub.calculate();
}
//Konstruktorinjektion
@Autowired
public Main(Sub sub) {
this.sub = sub;
}
}
Durch Hinzufügen der Autowired-Annotation werden Instanzen aus dem DI-Container in die Argumente von Feldern, Methoden und Konstruktoren eingefügt.
Wenn ich mich selbst injiziere, schreibe ich es übrigens mit der Annotation RequiredArgsConstructor von Lombok in der Bibliothek, wie im Artikel hier beschrieben.
Ein allgemeiner Vorteil ist, dass es einfacher ist, Komponententests zu schreiben. Ich denke das ist wahr.
Hier ist noch einmal das Beispiel am Anfang.
Main.java
public class Main {
public int hoge() {
var sub = new Sub();
return sub.calculate();
}
}
Wenn die Berechnungsmethode dieser Unterklasse für den Zugriff auf die Datenbank erforderlich wäre, wäre der Komponententest der Hauptklasse sehr schwierig.
Es kann jedoch getestet werden, indem die von DI injizierten Instanzen verspottet werden. Übrigens benutze ich Mockito, wenn ich einen Mock benutze.
Im Folgenden finden Sie eine Zusammenfassung der DI- und DI-Container in einem Wort.
DI: Übergeben einer Instanz einer Klasse, die von einer Klasse von außen abhängt DI-Container: Ein Container, der die zu injizierende Instanz verwaltet
Die Verwendung dieser hat den Vorteil, dass das Schreiben von Tests und das Verwalten des Bereichs einfacher ist.
Das ist alles für den Inhalt. Wir hoffen, Sie finden diesen Artikel hilfreich. Danke, dass Sie bis zum Ende für mich gelesen haben.
Offizielle Dokumentation Core Technologies
Recommended Posts