Ich verstehe die Vorteile der Abhängigkeitsinjektion selbst. Nehmen wir zum Beispiel den Frühling. Ich verstehe auch die Vorteile anderer Spring-Funktionen wie AOP, Helfer verschiedener Art usw. Ich frage mich nur, welche Vorteile die XML-Konfiguration bietet, z.
<bean id="Mary" class="foo.bar.Female">
<property name="age" value="23"/>
</bean>
<bean id="John" class="foo.bar.Male">
<property name="girlfriend" ref="Mary"/>
</bean>
im Vergleich zu einfachem alten Java-Code wie:
Female mary = new Female();
mary.setAge(23);
Male john = new Male();
john.setGirlfriend(mary);
Das ist einfacher zu debuggen, die Kompilierungszeit überprüft und kann von jedem verstanden werden, der nur Java kennt. Was ist der Hauptzweck eines Abhängigkeitsinjektions-Frameworks? (oder ein Stück Code, der seine Vorteile zeigt.)
UPDATE:
Im Falle von
IService myService;// ...
public void doSomething() {
myService.fetchData();
}
Wie kann das IoC-Framework erraten, welche Implementierung von myService injiziert werden soll, wenn es mehr als eine gibt? Wenn es nur eine Implementierung einer bestimmten Schnittstelle gibt und ich den IoC-Container automatisch für die Verwendung entscheiden lasse, wird sie unterbrochen, nachdem eine zweite Implementierung angezeigt wird. Und wenn es absichtlich nur eine mögliche Implementierung einer Schnittstelle gibt, müssen Sie sie nicht injizieren.
Es wäre wirklich interessant, eine kleine Konfiguration für IoC zu sehen, die die Vorteile zeigt. Ich benutze Spring schon eine Weile und kann ein solches Beispiel nicht liefern. Und ich kann einzelne Zeilen anzeigen, die die Vorteile von Ruhezustand, DWR und anderen von mir verwendeten Frameworks demonstrieren.
UPDATE 2:
Mir ist klar, dass die IoC-Konfiguration ohne erneutes Kompilieren geändert werden kann. Ist es wirklich so eine gute Idee? Ich kann verstehen, wenn jemand DB-Anmeldeinformationen ändern möchte, ohne sie neu zu kompilieren - er ist möglicherweise kein Entwickler. Wie oft ändert in Ihrer Praxis eine andere Person als der Entwickler die IoC-Konfiguration? Ich denke, dass es für Entwickler keine Anstrengung gibt, diese bestimmte Klasse neu zu kompilieren, anstatt die Konfiguration zu ändern. Und für Nicht-Entwickler möchten Sie wahrscheinlich sein Leben einfacher machen und eine einfachere Konfigurationsdatei bereitstellen.
UPDATE 3:
Externe Konfiguration der Zuordnung zwischen Schnittstellen und ihren konkreten Implementierungen
Was ist so gut daran, es zu erweitern? Sie machen nicht Ihren gesamten Code extern, während Sie dies definitiv können - platzieren Sie ihn einfach in der Datei ClassName.java.txt, lesen und kompilieren Sie manuell im laufenden Betrieb - wow, Sie haben eine Neukompilierung vermieden. Warum sollte das Kompilieren vermieden werden?!
Sie sparen Codierungszeit, da Sie Zuordnungen deklarativ und nicht in einem Prozedurcode bereitstellen
Ich verstehe, dass manchmal deklarativer Ansatz Zeit spart. Zum Beispiel deklariere ich nur einmal, dass eine Zuordnung zwischen einer Bean-Eigenschaft und einer DB-Spalte und dem Ruhezustand diese Zuordnung beim Laden, Speichern, Erstellen von SQL basierend auf HSQL usw. verwendet. Hier funktioniert der deklarative Ansatz. Im Fall von Spring (in meinem Beispiel) hatte die Deklaration mehr Zeilen und die gleiche Ausdruckskraft wie der entsprechende Code. Wenn es ein Beispiel gibt, bei dem eine solche Deklaration kürzer als Code ist, würde ich es gerne sehen.
Das Inversion of Control-Prinzip ermöglicht ein einfaches Testen von Einheiten, da Sie echte Implementierungen durch gefälschte ersetzen können (z. B. das Ersetzen der SQL-Datenbank durch eine In-Memory-Datenbank).
Ich verstehe die Inversion der Kontrollvorteile (ich ziehe es vor, das hier diskutierte Entwurfsmuster als Abhängigkeitsinjektion zu bezeichnen, da IoC allgemeiner ist - es gibt viele Arten der Kontrolle, und wir invertieren nur eine davon - die Kontrolle der Initialisierung). Ich habe gefragt, warum jemand jemals etwas anderes als eine Programmiersprache dafür braucht. Ich kann echte Implementierungen definitiv durch gefälschte implementieren, indem ich Code verwende. Und dieser Code drückt dasselbe aus wie die Konfiguration - er initialisiert nur Felder mit gefälschten Werten.
mary = new FakeFemale();
Ich verstehe die Vorteile von DI. Ich verstehe nicht, welche Vorteile die externe XML-Konfiguration im Vergleich zur Konfiguration von Code bietet, der dasselbe tut. Ich denke nicht, dass das Kompilieren vermieden werden sollte - ich kompiliere jeden Tag und bin noch am Leben. Ich denke, die Konfiguration von DI ist ein schlechtes Beispiel für einen deklarativen Ansatz. Die Deklaration kann nützlich sein, wenn sie einmal deklariert wird UND mehrmals auf unterschiedliche Weise verwendet wird - wie z. B. im Ruhezustand cfg, wo die Zuordnung zwischen Bean-Eigenschaft und DB-Spalte zum Speichern, Laden, Erstellen von Suchabfragen usw. verwendet wird. Die Spring DI-Konfiguration kann problemlos übersetzt werden Konfigurieren von Code, wie am Anfang dieser Frage, kann es nicht? Und es wird nur für die Bean-Initialisierung verwendet, nicht wahr? Was bedeutet, dass ein deklarativer Ansatz hier nichts hinzufügt, oder?
Wenn ich die Zuordnung für den Ruhezustand deklariere, gebe ich nur einige Informationen für den Ruhezustand an, und es funktioniert basierend darauf - ich sage ihm nicht, was zu tun ist. Im Falle des Frühlings sagt meine Erklärung dem Frühling genau, was zu tun ist - warum also deklarieren, warum nicht einfach?
LETZTES UPDATE:
Leute, viele Antworten erzählen mir von der Abhängigkeitsinjektion, von der ich weiß, dass sie gut ist. Die Frage bezieht sich auf den Zweck der DI-Konfiguration anstelle der Initialisierung von Code. Ich denke eher, dass die Initialisierung von Code kürzer und klarer ist. Die einzige Antwort, die ich bisher auf meine Frage erhalten habe, ist, dass ein erneutes Kompilieren vermieden wird, wenn sich die Konfiguration ändert. Ich denke, ich sollte eine andere Frage stellen, da es für mich ein großes Geheimnis ist, warum das Kompilieren in diesem Fall vermieden werden sollte.