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.
quelle
Antworten:
Für mich liegt einer der Hauptgründe für die Verwendung eines IoC (und die Verwendung einer externen Konfiguration) in den beiden Bereichen:
Testen
Wenn Sie Ihre Tests in drei Szenarien aufteilen (was bei der Entwicklung in großem Maßstab ziemlich normal ist):
Was Sie tun möchten, ist für die letzten beiden Testszenarien (Integration & Black Box), keinen Teil der Anwendung neu zu kompilieren.
Wenn Sie in einem Ihrer Testszenarien die Konfiguration ändern müssen (z. B. eine andere Komponente verwenden, um eine Bankintegration nachzuahmen, oder eine Leistungslast ausführen), kann dies problemlos gehandhabt werden (dies unterliegt den Vorteilen der Konfiguration der DI-Seite eines IoC obwohl.
Wenn Ihre App entweder an mehreren Standorten (mit unterschiedlicher Server- und Komponentenkonfiguration) verwendet wird oder eine sich ändernde Konfiguration in der Live-Umgebung aufweist, können Sie in den späteren Testphasen überprüfen, ob die App diese Änderungen verarbeitet.
Produktion
Als Entwickler haben Sie (und sollten) keine Kontrolle über die Produktionsumgebung (insbesondere wenn Ihre App an mehrere Kunden oder separate Sites verteilt wird). Für mich ist dies der eigentliche Vorteil der Verwendung einer IoC- und einer externen Konfiguration , da es an der Infrastruktur- / Produktionsunterstützung liegt, die Live-Umgebung zu optimieren und anzupassen, ohne zu Entwicklern und durch Tests zurückkehren zu müssen (höhere Kosten, wenn sie nur eine Komponente verschieben möchten).
Zusammenfassung
Die Hauptvorteile der externen Konfiguration eines IoC bestehen darin, anderen (Nicht-Entwicklern) die Möglichkeit zu geben, Ihre Anwendung zu konfigurieren. Nach meiner Erfahrung ist dies nur unter bestimmten Umständen nützlich:
In der Praxis habe ich festgestellt, dass es im Laufe der Zeit besser ist, jemand anderem die Möglichkeit zu geben, die Konfiguration zu ändern, selbst wenn Sie etwas entwickeln, auf das Sie die Kontrolle über die Umgebung haben.
Hinweis: Die Anwendung bezieht sich auf die vollständige Lösung (nicht nur auf die ausführbare Datei), also auf alle Dateien, die für die Ausführung der Anwendung erforderlich sind .
quelle
Die Abhängigkeitsinjektion ist ein Codierungsstil, der seine Wurzeln in der Beobachtung hat, dass die Objektdelegierung normalerweise ein nützlicheres Entwurfsmuster als die Objektvererbung ist (dh das Objekt hat eine Beziehung, die nützlicher ist als das Objekt eine Beziehung). Eine weitere Zutat ist jedoch erforderlich, damit DI funktioniert, nämlich das Erstellen von Objektschnittstellen. Durch die Kombination dieser beiden leistungsstarken Entwurfsmuster erkannten Softwareentwickler schnell, dass sie flexiblen, lose gekoppelten Code erstellen konnten, und so entstand das Konzept der Abhängigkeitsinjektion. Erst als die Objektreflexion in bestimmten Hochsprachen verfügbar wurde, nahm DI wirklich Fahrt auf. Die Reflexionskomponente ist der Kern der meisten von heute. '
Eine Sprache muss sowohl normale objektorientierte Programmiertechniken als auch Objektschnittstellen und Objektreflexion (z. B. Java und C #) gut unterstützen. Während Sie Programme mit DI-Mustern in C ++ - Systemen erstellen können, verhindert die fehlende Reflexionsunterstützung in der eigentlichen Sprache, dass Anwendungsserver und andere DI-Plattformen unterstützt werden, und schränkt daher die Ausdruckskraft der DI-Muster ein.
Stärken eines Systems, das mit DI-Mustern aufgebaut ist:
Auf jeden Fall scheint DI-Code umständlicher zu sein. Die Nachteile all dieser XML-Dateien, die Objekte konfigurieren, die in andere Objekte eingefügt werden sollen, erscheinen schwierig. Dies ist jedoch der Punkt von DI-Systemen. Durch Ihre Fähigkeit, Codeobjekte als eine Reihe von Konfigurationseinstellungen zu mischen und abzugleichen, können Sie komplexe Systeme mit Code von Drittanbietern mit minimaler Codierung erstellen.
Das in der Frage bereitgestellte Beispiel berührt lediglich die Oberfläche der Ausdruckskraft, die eine ordnungsgemäß faktorisierte DI-Objektbibliothek bereitstellen kann. Mit etwas Übung und viel Selbstdisziplin stellen die meisten DI-Praktiker fest, dass sie Systeme erstellen können, die eine 100% ige Testabdeckung des Anwendungscodes aufweisen. Dieser eine Punkt allein ist außergewöhnlich. Dies ist keine 100% ige Testabdeckung einer kleinen Anwendung mit einigen hundert Codezeilen, sondern eine 100% ige Testabdeckung von Anwendungen mit hunderttausenden Codezeilen. Ich bin nicht in der Lage, andere Entwurfsmuster zu beschreiben, die dieses Maß an Testbarkeit bieten.
Sie haben insofern Recht, als eine Anwendung von nur 10 Codezeilen leichter zu verstehen ist als mehrere Objekte plus eine Reihe von XML-Konfigurationsdateien. Wie bei den leistungsstärksten Entwurfsmustern werden die Vorteile jedoch festgestellt, wenn Sie dem System weiterhin neue Funktionen hinzufügen.
Kurz gesagt, DI-basierte Anwendungen in großem Maßstab sind sowohl einfacher zu debuggen als auch leichter zu verstehen. Während die XML-Konfiguration nicht auf Kompilierungszeit überprüft ist, erhalten alle Anwendungsdienste, die diesem Autor bekannt sind, Fehlermeldungen, wenn sie versuchen, ein Objekt mit einer inkompatiblen Schnittstelle in ein anderes Objekt einzufügen. Die meisten bieten eine Überprüfungsfunktion, die alle bekannten Objektkonfigurationen abdeckt. Dies erfolgt einfach und schnell, indem überprüft wird, ob das zu injizierende Objekt A die von Objekt B für alle konfigurierten Objektinjektionen erforderliche Schnittstelle implementiert.
quelle
Dies ist eine etwas geladene Frage, aber ich stimme eher zu, dass große Mengen an XML-Konfiguration nicht wirklich viel Nutzen bringen. Ich mag es, wenn meine Anwendungen so leicht wie möglich von Abhängigkeiten sind, einschließlich der umfangreichen Frameworks.
Sie vereinfachen den Code häufig, haben aber auch einen Komplexitätsaufwand, der das Aufspüren von Problemen ziemlich schwierig macht (ich habe solche Probleme aus erster Hand gesehen, und mit reinem Java würde ich mich viel wohler fühlen).
Ich denke, es hängt ein bisschen vom Stil ab und davon, womit Sie vertraut sind. Fliegen Sie gerne Ihre eigene Lösung und haben Sie den Vorteil, sie genau zu kennen, oder setzen Sie auf vorhandene Lösungen, die sich als schwierig erweisen können, wenn die Konfiguration nicht stimmt. t genau richtig? Es ist alles ein Kompromiss.
Die XML-Konfiguration ist jedoch ein kleiner Ärger von mir ... Ich versuche, sie um jeden Preis zu vermeiden.
quelle
Jedes Mal, wenn Sie Ihren Code in Daten ändern können, machen Sie einen Schritt in die richtige Richtung.
Das Codieren von Daten bedeutet, dass Ihr Code selbst allgemeiner und wiederverwendbarer ist. Dies bedeutet auch, dass Ihre Daten möglicherweise in einer Sprache angegeben werden, die genau zu ihnen passt.
Eine XML-Datei kann auch in eine GUI oder ein anderes Tool eingelesen und leicht pragmatisch bearbeitet werden. Wie würden Sie das mit dem Codebeispiel machen?
Ich berücksichtige ständig Dinge, die die meisten Leute als Code in Daten implementieren würden. Dadurch wird der verbleibende Code VIEL sauberer. Ich finde es unvorstellbar, dass Leute ein Menü im Code und nicht als Daten erstellen - es sollte offensichtlich sein, dass es aufgrund des Boilerplates einfach falsch ist, es im Code zu tun.
quelle
Der Grund für die Verwendung eines DI-Containers besteht darin, dass in Ihrem Code nicht eine Milliarde Eigenschaften vorkonfiguriert sein müssen, die lediglich Getter und Setter sind. Möchten Sie wirklich alle mit neuem X () fest codieren? Natürlich können Sie eine Standardeinstellung festlegen, aber der DI-Container ermöglicht die Erstellung von Singletons, was äußerst einfach ist und es Ihnen ermöglicht, sich auf die Details des Codes zu konzentrieren, nicht auf die sonstige Aufgabe, ihn zu initialisieren.
Mit Spring können Sie beispielsweise die InitializingBean-Schnittstelle implementieren und eine afterPropertiesSet-Methode hinzufügen (Sie können auch eine "init-Methode" angeben, um zu vermeiden, dass Ihr Code an Spring gekoppelt wird). Mit diesen Methoden können Sie sicherstellen, dass alle in Ihrer Klasseninstanz als Feld angegebenen Schnittstellen beim Start korrekt konfiguriert sind. Anschließend müssen Sie Ihre Getter und Setter nicht mehr auf Null prüfen (vorausgesetzt, Sie lassen zu, dass Ihre Singletons threadsicher bleiben ).
Darüber hinaus ist es viel einfacher, komplexe Initialisierungen mit einem DI-Container durchzuführen, als sie selbst durchzuführen. Zum Beispiel unterstütze ich bei der Verwendung von XFire (nicht CeltiXFire, wir verwenden nur Java 1.4). Die App verwendete Spring, aber leider den Konfigurationsmechanismus services.xml von XFire. Wenn eine Sammlung von Elementen deklarieren musste, dass sie NULL oder mehr Instanzen anstelle von EINER oder mehreren Instanzen hatte, musste ich einen Teil des bereitgestellten XFire-Codes für diesen bestimmten Dienst überschreiben.
In seinem Spring Beans-Schema sind bestimmte XFire-Standardeinstellungen definiert. Wenn wir also Spring zum Konfigurieren der Dienste verwendet hätten, könnten die Beans verwendet worden sein. Stattdessen musste ich eine Instanz einer bestimmten Klasse in der Datei services.xml angeben, anstatt die Beans zu verwenden. Dazu musste ich den Konstruktor bereitstellen und die in der XFire-Konfiguration deklarierten Referenzen einrichten. Die wirkliche Änderung, die ich vornehmen musste, erforderte, dass ich eine einzelne Klasse überlastete.
Dank der Datei services.xml musste ich jedoch vier neue Klassen erstellen und ihre Standardeinstellungen entsprechend den Standardeinstellungen in den Spring-Konfigurationsdateien in ihren Konstruktoren festlegen. Wenn wir die Spring-Konfiguration hätten verwenden können, hätte ich einfach sagen können:
Stattdessen sah es eher so aus:
Das Nettoergebnis ist also, dass vier zusätzliche, meist sinnlose Java-Klassen zur Codebasis hinzugefügt werden mussten, um den Effekt zu erzielen, den eine zusätzliche Klasse und einige einfache Abhängigkeitscontainerinformationen erzielten. Dies ist nicht die "Ausnahme, die die Regel beweist", sondern die Regel ... Der Umgang mit Macken im Code ist viel sauberer, wenn die Eigenschaften bereits in einem DI-Container bereitgestellt werden und Sie sie einfach an eine spezielle Situation anpassen. was meistens passiert.
quelle
Ich habe deine Antwort
Es gibt offensichtlich Kompromisse bei jedem Ansatz, aber externalisierte XML-Konfigurationsdateien sind nützlich für die Unternehmensentwicklung, bei der Build-Systeme zum Kompilieren des Codes und nicht Ihrer IDE verwendet werden. Wenn Sie das Build-System verwenden, möchten Sie möglicherweise bestimmte Werte in Ihren Code einfügen - beispielsweise die Version des Builds (was schmerzhaft sein kann, wenn Sie jedes Mal, wenn Sie kompilieren, manuell aktualisieren müssen). Der Schmerz ist größer, wenn Ihr Build-System Code von einem Versionskontrollsystem abruft. Wenn Sie einfache Werte zur Kompilierungszeit ändern, müssen Sie eine Datei ändern, festschreiben, kompilieren und dann jedes Mal für jede Änderung zurücksetzen. Dies sind keine Änderungen, die Sie in Ihre Versionskontrolle übernehmen möchten.
Andere nützliche Anwendungsfälle in Bezug auf das Build-System und externe Konfigurationen:
Update: Alle obigen Beispiele betrafen Dinge, die nicht unbedingt Abhängigkeiten von Klassen erforderten. Sie können jedoch problemlos Fälle erstellen, in denen sowohl ein komplexes Objekt als auch eine Automatisierung erforderlich sind - zum Beispiel:
quelle
Sie müssen Ihren Code nicht jedes Mal neu kompilieren, wenn Sie Änderungen an der Konfiguration vornehmen. Dies vereinfacht die Programmbereitstellung und -wartung. Zum Beispiel können Sie eine Komponente mit nur einer Änderung in der Konfigurationsdatei gegen eine andere austauschen.
quelle
Sie können eine neue Implementierung für Freundin einfügen. So kann eine neue Frau injiziert werden, ohne Ihren Code neu zu kompilieren.
(Oben wird davon ausgegangen, dass Female und HotFemale dieselbe GirlfFriend-Schnittstelle implementieren.)
quelle
In der .NET-Welt bieten die meisten IoC-Frameworks sowohl XML- als auch Code-Konfiguration.
StructureMap und Ninject verwenden beispielsweise fließende Schnittstellen, um Container zu konfigurieren. Sie müssen keine XML-Konfigurationsdateien mehr verwenden. Spring, das auch in .NET vorhanden ist, stützt sich stark auf XML-Dateien, da es seine historische Hauptkonfigurationsoberfläche ist. Es ist jedoch weiterhin möglich, Container programmgesteuert zu konfigurieren.
quelle
Einfache Kombination von Teilkonfigurationen zu einer endgültigen vollständigen Konfiguration.
In Webanwendungen werden beispielsweise Modell, Ansicht und Controller normalerweise in separaten Konfigurationsdateien angegeben. Verwenden Sie den deklarativen Ansatz, den Sie beispielsweise laden können:
Oder laden Sie mit einer anderen Benutzeroberfläche und einigen zusätzlichen Controllern:
Um dasselbe im Code zu tun, ist eine Infrastruktur zum Kombinieren von Teilkonfigurationen erforderlich. Nicht unmöglich im Code, aber sicherlich einfacher mit einem IoC-Framework.
quelle
Oft ist der wichtige Punkt, wer die Konfiguration ändert, nachdem das Programm geschrieben wurde. Bei der Konfiguration im Code gehen Sie implizit davon aus, dass die Person, die ihn ändert, über dieselben Fähigkeiten und denselben Zugriff auf den Quellcode usw. verfügt wie der ursprüngliche Autor.
In Produktionssystemen ist es sehr praktisch, eine Teilmenge von Einstellungen (z. B. Alter in Ihrem Beispiel) in eine XML-Datei zu extrahieren und z. B. Systemadministratoren oder Supportmitarbeitern zu erlauben, den Wert zu ändern, ohne ihnen die volle Macht über den Quellcode oder andere Einstellungen zu geben - oder nur um sie von Komplexität zu isolieren.
quelle
Aus Sicht des Frühlings kann ich Ihnen zwei Antworten geben.
Erstens ist die XML-Konfiguration nicht die einzige Möglichkeit, die Konfiguration zu definieren. Die meisten Dinge können mithilfe von Anmerkungen konfiguriert werden, und die Dinge, die mit XML erledigt werden müssen, sind Konfigurationen für Code, den Sie sowieso nicht schreiben, wie z. B. einen Verbindungspool, den Sie aus einer Bibliothek verwenden. Spring 3 enthält eine Methode zum Definieren der DI-Konfiguration mit Java, ähnlich der handgerollten DI-Konfiguration in Ihrem Beispiel. Die Verwendung von Spring bedeutet also nicht, dass Sie eine XML-basierte Konfigurationsdatei verwenden müssen.
Zweitens ist Spring viel mehr als nur ein DI-Framework. Es verfügt über viele weitere Funktionen, einschließlich Transaktionsmanagement und AOP. Die Spring XML-Konfiguration mischt alle diese Konzepte zusammen. Oft spezifiziere ich in derselben Konfigurationsdatei Bean-Abhängigkeiten, Transaktionseinstellungen und füge Beans mit Sitzungsbereich hinzu, die tatsächlich mit AOP im Hintergrund verarbeitet wurden. Ich finde, dass die XML-Konfiguration einen besseren Ort bietet, um all diese Funktionen zu verwalten. Ich bin auch der Meinung, dass die auf Anmerkungen basierende Konfiguration und die XML-Konfiguration besser skaliert werden können als die Java-basierte Konfiguration.
Aber ich verstehe Ihren Standpunkt und es ist nichts Falsches daran, die Konfiguration der Abhängigkeitsinjektion in Java zu definieren. Normalerweise mache ich das selbst in Unit-Tests und wenn ich an einem Projekt arbeite, das klein genug ist, dass ich kein DI-Framework hinzugefügt habe. Normalerweise spezifiziere ich keine Konfiguration in Java, da dies für mich die Art von Installationscode ist, den ich nicht schreiben möchte, wenn ich mich für Spring entschieden habe. Dies ist jedoch eine Präferenz. Dies bedeutet jedoch nicht, dass die XML-Konfiguration der Java-basierten Konfiguration überlegen ist.
quelle
Spring hat auch einen Eigenschaftenlader. Mit dieser Methode setzen wir umgebungsabhängige Variablen (zB Entwicklung, Test, Akzeptanz, Produktion, ...). Dies könnte beispielsweise die Warteschlange sein, die abgehört werden soll.
Wenn es keinen Grund gibt, warum sich die Eigenschaft ändern würde, gibt es auch keinen Grund, sie auf diese Weise zu konfigurieren.
quelle
Ihr Fall ist sehr einfach und benötigt daher keinen IoC-Container (Inversion of Control) wie Spring. Wenn Sie dagegen "auf Schnittstellen programmieren, nicht auf Implementierungen" (was in OOP eine gute Praxis ist), können Sie folgenden Code haben:
(Beachten Sie, dass der Typ von myService IService ist - eine Schnittstelle, keine konkrete Implementierung). Jetzt kann es praktisch sein, Ihren IoC-Container während der Initialisierung automatisch die richtige konkrete Instanz von IService bereitstellen zu lassen. Wenn Sie über viele Schnittstellen und viele Implementierungen verfügen, kann es mühsam sein, dies von Hand zu tun. Hauptvorteile eines IoC-Containers (Dependency Injection Framework) sind:
quelle
Das Initialisieren in einer XML-Konfigurationsdatei vereinfacht Ihre Debugging- / Anpassungsarbeit mit einem Client, auf dessen Computern Ihre App bereitgestellt ist. (Weil es keine Neukompilierung + Ersetzen von Binärdateien erfordert)
quelle
Einer der attraktivsten Gründe ist das " Hollywood-Prinzip ": Rufen Sie uns nicht an, wir rufen Sie an. Eine Komponente ist nicht erforderlich, um die Suche nach anderen Komponenten und Diensten selbst durchzuführen. stattdessen werden sie automatisch bereitgestellt. In Java bedeutet dies, dass keine JNDI-Lookups mehr innerhalb der Komponente durchgeführt werden müssen.
Es ist auch viel einfacher, eine Komponente einzeln zu testen: Anstatt ihr eine tatsächliche Implementierung der benötigten Komponenten zu geben, verwenden Sie einfach (möglicherweise automatisch generierte) Mocks.
quelle