Frage

Ich verstehe Vorteile der Dependency Injection selbst. Lassen Sie uns zum Beispiel Frühling nehmen. Ich verstehe auch Vorteile anderen Frühling featureslike AOP, Helfer verschiedener Arten, etc. Ich frage mich nur, was die Vorteile der XML-Konfiguration sind wie zum Beispiel:

<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 normalen alten Java-Code wie:

Female mary = new Female();
mary.setAge(23);
Male john = new Male();
john.setGirlfriend(mary);

, die einfachen Debuggen, kompiliert Zeit überprüft und kann von jedermann verstanden werden, die nur Java kennt. Also, was ist der Hauptzweck eines Dependency Injection-Framework? (Oder ein Stück Code, das zeigt seine Vorteile.)


UPDATE:
Im Fall von

IService myService;// ...
public void doSomething() {  
  myService.fetchData();
}

Wie kann IoC Rahmen erraten, welche die Umsetzung von myService I injiziert werden soll, wenn es mehr als eine? Wenn es nur eine Implementierung der Schnittstelle gegeben ist, und ich lasse automatisch IoC-Container entscheiden, es zu verwenden, wird es gebrochen werden, nachdem eine zweite Implementierung erscheint. Und wenn es absichtlich nur eine mögliche Implementierung einer Schnittstelle ist, dann müssen Sie es nicht injizieren.

Es wäre wirklich interessant sein kleines Stück Konfiguration für IoC, um zu sehen, die daraus entstehenden Vorteile zeigt. Ich habe für eine Weile Frühling benutzen und ich kann nicht solches Beispiel liefern. Und ich kann einzelne Linien zeigt die Vorteile von Hibernate, dwr demonstrieren und anderen Frameworks, die ich verwende.


UPDATE 2:
Ich weiß, dass IoC Konfiguration kann ohne erneute Kompilierung geändert werden. Ist es wirklich so eine gute Idee? Ich kann verstehen, wenn jemand will, ohne DB-Anmeldeinformationen ändern, neu zu kompilieren - er kann nicht Entwickler. In Ihrer Praxis, wie oft jemand anderes als Entwickler ändert IoC Konfiguration? Ich denke, dass für Entwickler gibt es keine Anstrengung ist, dass bestimmte Klasse statt Ändern Konfiguration neu zu kompilieren. Und für Nicht-Entwickler würden Sie wahrscheinlich wollen sein Leben leichter machen und etwas einfache Konfigurationsdatei zur Verfügung stellen.


UPDATE 3:

  

Externe Konfiguration Zuordnung zwischen Schnittstellen und den konkreten Implementierungen

Was ist so gut es extenal zu machen? Sie müssen nicht den gesamten Code externen machen, während Sie können auf jeden Fall - einfach in ClassName.java.txt Datei platzieren, lesen und manuell on the fly kompilieren - wow, vermied Sie Neukompilieren. Warum sollte Kompilieren vermieden werden?

  

Sie sparen Codierung Zeit, weil Sie Zuordnungen deklarativ bieten, nicht in einem prozeduralen Code

Ich verstehe, dass manchmal deklarativen Ansatz spart Zeit. Zum Beispiel erkläre ich nur einmal eine Zuordnung zwischen einer Bean-Eigenschaft und einer DB-Säule und Hibernate dieser Zuordnung verwendet beim Laden, Speicher, Gebäude SQL basierend auf HSQL, etc. Dies ist, wo der deklarative Ansatz funktioniert. Im Fall von Spring (in meinem Beispiel), hatte Erklärung mehr Linien und hatte die gleiche Aussagekraft wie die entsprechenden Code. Wenn es ein Beispiel ist, wenn eine solche Erklärung kürzer als Code -. Ich möchte es sehen

  

Invertierung Prinzip Steuerung ermöglicht eine einfache Unit-Tests, weil Sie echte Implementierungen mit gefälschten ersetzen können (wie ersetzen SQL-Datenbank mit einer In-Memory-one)

Ich verstehe Umkehrung der Steuervorteile (Ich ziehe das Designmuster hier als Dependency Injection diskutiert zu nennen, weil IoC allgemeiner ist - es gibt viele Arten von Kontrolle sind, und wir sind Umkehren nur einer von ihnen - Kontrolle der Initialisierung) . Ich wurde gefragt, warum jemand jemals etwas anderes als eine Programmiersprache für die es braucht. Ich kann auf jeden Fall echte Implementierungen mit gefälschten ersetzen Code. Und diese Code elbe wie Konfiguration auszudrücken -. Es wird nur Felder mit falschen Werten initialisieren

mary = new FakeFemale();

ich Vorteile von DI verstehen. Ich verstehe nicht, welche Vorteile durch externe XML-Konfiguration im Vergleich zu der Konfiguration Code hinzugefügt werden, die das gleiche tut. Ich glaube nicht, dass comBohlen sollte vermieden werden - ich jeden Tag kompilieren und ich bin immer noch am Leben. Ich denke, Konfiguration von DI ist schlechtes Beispiel von deklarativen Ansatz. Erklärung kann nützlich sein, wenn einmal deklariert und wird oft auf unterschiedliche Weise verwendet - wie Hibernate cfg, wo Zuordnung zwischen Bean-Eigenschaft und DB-Säule wird zum Speichern, Laden verwendet, Suchanfrage Gebäude usw. Frühling DI-Konfiguration kann leicht übersetzt werden Konfigurieren von Code, wie am Anfang dieser Frage kann es nicht? Und es ist nur für die Bohne Initialisierung verwendet wird, ist es nicht? Was bedeutet, einen deklarativen Ansatz fügt nichts hier, nicht wahr?

Wenn ich Mapping erklären wintern, ich gebe nur einige Informationen überwintern, und es funktioniert auf ihr basiert - ich sage es nicht, was zu tun ist. Im Fall einer Feder, sagt meine Erklärung Feder genau wht zu tun - warum also erklären, warum nicht tun Sie es einfach


Letzte Aktualisierung:
Jungs sind eine Menge Antworten mich über Dependency Injection zu sagen, was ich weiß, ist GUT. Die Frage ist, über Zweck der DI-Konfiguration anstelle Code der Initialisierung - ich neige dazu zu glauben, dass Code initialisiert ist kürzer und klarer. Die einzige Antwort, die ich bekam so weit auf meine Frage, ist, dass es vermeidet, neu zu kompilieren, wenn die Konfigurationsänderungen. Ich denke, ich sollte eine andere Frage veröffentlichen, weil es ein großes Geheimnis für mich ist, warum Kompilieren in diesem Fall vermieden werden sollte.

War es hilfreich?

Lösung

Für mich einer der Hauptgründe, warum ein IoC zu verwenden (und die Verwendung von externer Konfiguration zu machen) ist um die beiden Bereiche:

  • Testing
  • Produktion Wartung

Prüfung

Wenn Sie teilen Sie Ihre Tests in drei Szenarien (die in großem Maßstab Entwicklung ziemlich normal ist):

  1. Unit-Tests
  2. Integrationstest
  3. Black-Box-Tests

Was wollen Sie zu tun ist in den letzten beiden Testszenarien (Integration & Black Box), neu kompilieren ist nicht Teil der Anwendung.

Falls Ihre Testszenarien benötigen Sie die Konfiguration ändern (dh eine andere Komponente verwenden, um eine Bank Integration zu imitieren, oder eine Leistung Last tun), kann dies leicht gehandhabt werden (dies kommt unter den Vorteilen der DI Konfiguration obgleich Seite eines IoC.

Zusätzlich wenn Ihre Anwendung wird entweder an mehreren Standorten (mit verschiedenen Server- und Komponentenkonfiguration) oder eine Veränderung Konfiguration auf der Live-Umgebung, um die späteren Stadien der Prüfung verwenden kann, um sicherzustellen, dass die App diese Änderungen behandelt.

Produktion

Als Entwickler Sie dies nicht tun (und sollte nicht) haben die Kontrolle über die Produktionsumgebung (insbesondere dann, wenn Ihre Anwendung auf mehrere Kunden oder getrennte Standorte verteilt wird), dies ist für mich der eigentliche Vorteil von sowohl einen IoC mit und externe Konfiguration, wie sie ist bis zur Infrastruktur / Produktionsunterstützung zu optimieren und die Live-Umgebung anpassen, ohne wieder an den Entwickler zu gehen und durch Test (höhere Kosten, wenn alles, was sie wollen, ist zu tun, um eine Komponente zu bewegen).

Zusammenfassung

Die wichtigsten Vorteile, die externe Konfiguration eines IoC kommt von anderen (nicht-Entwickler) die Macht, Ihre Anwendung zu konfigurieren, in meiner Erfahrung ist dies unter einer begrenzten Reihe von Umständen nur dann sinnvoll:

  • Die Anwendung ist auf mehrere Standorte / Clients verteilt, wo Umgebungen unterscheiden.
  • Begrenzte Entwicklung Steuerung / Eingang über die Produktionsumgebung und Einrichtung.
  • Test-Szenarien.

In der Praxis habe ich gefunden, dass selbst, wenn etwas zu entwickeln, die Sie die Kontrolle zu tun haben über die Umwelt wird es läuft auf sein, im Laufe der Zeit ist es besser, jemand zu geben, sonst die Fähigkeiten, die Konfiguration zu ändern:

  • Bei der Entwicklung Sie nicht wissen, wann es ändern wird (die App ist so nützlich, Ihr Unternehmen verkauft es an jemand anderen).
  • Ich will nicht mit der Änderung der Code jedes Mal eine kleine Änderung angefordert wird geklebt werden, die durch den Aufbau und die Verwendung eines guten Konfigurationsmodell behandelt werden können.

Hinweis: Anwendung bezieht sich auf die vollständige Lösung (nicht nur die ausführbare Datei), so dass alle Dateien für die Anwendung erforderlich sind, um

.

Andere Tipps

Dependency Injection ist eine Codierungsstil, der seine Wurzeln in der Beobachtung, hat die Delegation des Objekt ist in der Regel ein nützliches Entwurfsmuster als Objektvererbung (das heißt, das Objekt-ein-Beziehung ist nützlicher als das Objekt ist-ein-Beziehung). Ein weiterer Bestandteil ist jedoch notwendig, für DI zu arbeiten, dass Objektschnittstellen zu schaffen. Die Kombination realisiert diese zwei leistungsstarke Design Patterns Software-Ingenieure schnell, dass sie lose gekoppelten Code flexibel schaffen könnte und somit das Konzept der Dependency Injection war geboren. Es war jedoch nicht bis Objektreflexion in bestimmten Hochsprachen zur Verfügung stand, die DI auszog wirklich. Die Reflexionskomponente ist der Kern die meisten DI heutigen Systeme heute, weil die wirklich cool Aspekte von DI erfordern die Fähigkeit, sie in andere Objekte programmatisch Objekte auszuwählen und zu konfigurieren und injizieren sich unter Verwendung eines Systems externe und unabhängige zu den Objekten.

muss eine Sprache für beide normalen Object Oriented gute Unterstützung bieten Programmiertechniken sowie Unterstützung für Objektschnittstellen und Objektreflexion (zB Java und C #). Während Sie Programme mit DI-Mustern in C ++ Systemen ihren Mangel an Reflexion Unterstützung innerhalb der Sprache richtigen verhindert, dass er die Unterstützung Anwendungsservern und andere DI-Plattformen und daher begrenzt die Aussagekraft der DI-Muster aufbauen können.

Stärken eines Systems gebaut mit DI-Muster:

  1. DI-Code ist viel einfacher wiederverwenden als ‚abhängig‘ Funktionalität in gut definierte Schnittstellen hochgerechnet, so dass separate Objekte, deren Konfiguration durch eine geeignete Anwendungsplattform abgewickelt wird in andere Objekte nach Belieben angeschlossen werden.
  2. DI-Code ist viel einfacher zu testen. Die Funktionalität, die von dem Objekt ausgedrückt kann durch den Bau von ‚mock‘ Objekten in einer schwarzen Box getestet werden Implementierung der Schnittstellen, die von der Anwendungslogik erwartet.
  3. DI-Code ist flexibler. Es ist angeboren Code lose gekoppelt - auf die Spitze. Dies ermöglicht es dem Programmierer zu wählen, und zu wählen, wie Objekte angeschlossen ausschließlich auf ihre erforderlichen Schnittstellen an einem Ende und ihre ausgedrückt Schnittstellen auf der anderen basieren.
  4. Externe (XML) Konfiguration von DI-Objekte bedeutet, dass andere Ihren Code in unvorhergesehene Richtungen anpassen können.
  5. Externe Konfiguration ist auch eine Trennung von Sorge Muster, dass alle Probleme der Objektinitialisierung und Objekt Interdependenz Management kann vom Anwendungsserver behandelt werden.
  6. Beachten Sie, dass externe Konfiguration ist nicht das DI-Muster zu verwenden, erforderlich, für einfache Verbindungen ein kleiner Baumeister Objekt oft ausreichend ist. Es ist ein Kompromiss in der Flexibilität zwischen den beiden. Ein Builder-Objekt ist nicht so flexibel eine Option als eine von außen sichtbaren Konfigurationsdatei. Der Entwickler des DI-System müssen die Vorteile der Flexibilität über Bequemlichkeit wiegen, wobei darauf geachtet, dass kleine, feinkörnig Kontrolle über Objektbau wie in einer Konfigurationsdatei ausgedrückt kann Verwirrung und Wartungskosten auf der ganzen Linie erhöhen.

Auf jeden Fall DI Code umständlicher zu sein scheint, der die Nachteile all diese XML-Dateien, die die Objekte konfigurieren in andere Objekte zu injizierenden erscheint schwierig. Dies ist jedoch der Punkt der DI-Systeme. Ihre Fähigkeit und Matchcode zu mischen Objekte als eine Reihe von Konfigurationseinstellungen ermöglicht es Ihnen, komplexe Systeme mit 3rd-Party-Code mit minimaler Codierung auf Ihrer Seite zu bauen.

Das Beispiel in der Frage enthält lediglich berührt die Oberfläche der Ausdruckskraft, die ein richtig DI Objektbibliothek einkalkuliert zur Verfügung stellen kann. Mit etwas Übung und viel Selbstdisziplin meisten DI Praktiker feststellen, dass sie Systeme bauen, die 100% Testabdeckung des Anwendungscodes haben. Dieser Punkt allein ist außergewöhnlich. Dies ist nicht zu 100% Testabdeckung einer kleinen Anwendung von einigen hundert Zeilen Code, aber 100% Testabdeckung von apdungen Hunderttausende von Codezeilen umfasst. Ich bin mit einem Verlust von anderen Entwurfsmuster beschreiben zu können, die diese Ebene der Testbarkeit bietet.

Sie sind richtig, dass eine Anwendung von nur 10s von Zeilen Code einfacher ist, als mehrere Objekte sowie eine Reihe von XML-Konfigurationsdateien zu verstehen. Doch wie bei den meisten leistungsfähigen Design-Mustern werden die Verstärkungen gefunden, wie Sie neue Funktionen zu dem System hinzuzufügen fortzusetzen.

Kurz gesagt, in großem Maßstab DI-basierte Anwendungen sind sowohl einfacher zu debuggen und leichter zu verstehen. Während die XML-Konfiguration ‚kompilieren Zeit geprüft‘ nicht alle Anwendungsdienste, die dieser Autor ist sich bewusst, liefert der Entwickler mit Fehlermeldungen, wenn sie ein Objekt mit einer nicht kompatiblen Schnittstelle in ein anderes Objekt zu injizieren versuchen. Und die meisten bieten einen ‚Check‘ -Funktion, die alle bekannten Objekte Konfigurationen abdeckt. Dies ist leicht und schnell durchgeführt durch Prüfen, dass die auszuformende injizierten Objekt A die Schnittstelle von Objekt B für alle konfigurierten Objekte Injektionen erforderlich implementiert.

Das ist ein bisschen von einer geladenen Frage, aber ich eher zustimmen, dass große Mengen an XML-Konfiguration nicht wirklich zu viel Nutzen betragen. Ich mag meine Anwendungen wie Licht auf Abhängigkeiten wie möglich sein, auch die kräftigen Frameworks.

Sie den Code ein großer Teil der Zeit vereinfachen, aber sie haben auch einen Overhead in der Komplexität, die Probleme aufzuspüren ziemlich schwierig macht (ich habe solche Probleme aus erster Hand gesehen, und gerade Java würde ich viel wohler Umgang mit sein) .

Ich denke, es auf Stil hängt ein wenig, und was sind Sie bequem mit ... machen Sie Ihre eigene Lösung fliegen und haben den Vorteil, es von innen nach außen zu wissen, oder Bank auf bestehende Lösungen, die als schwierig erweisen können, wenn die Konfiguration ist nicht nur richtig? Es ist alles ein Kompromiss.

Allerdings XML-Konfiguration ist ein bisschen ein Haustier ärgern von mir ... Ich versuche es zu vermeiden, um jeden Preis.

Jedes Mal, können Sie Ihren Code, um Daten ändern Sie einen Schritt in der richtigen Richtung zu machen.

Codierung etwas wie Daten bedeuten, dass der Code selbst allgemeiner und wiederverwendbar ist. Es bedeutet auch, dass Ihre Daten in einer Sprache angegeben werden, dass es genau passt.

Auch kann eine XML-Datei in einem GUI oder ein anderes Werkzeug und leicht pragmatisch manipulierte gelesen werden. Wie würden Sie das tun, mit dem Codebeispiel?

Ich bin Factoring Dinge ständig die meisten Menschen als Code in Daten implementieren würden, macht es, was Code viel sauberer bleibt. Ich finde es nicht denkbar, dass die Menschen ein Menü in Code erstellen, anstatt wie Daten - es sollte klar sein, dass es im Code zu tun, weil der Text einfach falsch ist

.

Der Grund, einen DI-Container für die Verwendung sind, dass Sie eine Milliarde Eigenschaften vorkonfiguriert in Ihrem Code haben müssen Getter und Setter nicht, die sind einfach. Wollen Sie wirklich alle, die mit neuen X codieren ()? Sicher, können Sie einen Standard, aber die DI-Container ermöglichen die Erstellung von Singletons, die extrem einfach und ermöglicht es Ihnen, über die Details des Codes zu konzentrieren und nicht auf die verschieden Aufgabe es zu initialisieren.

Zum Beispiel, Frühling können Sie die InitializingBean Schnittstelle implementieren und füge eine afterPropertiesSet Methode (Sie können auch ein „init-Methode“ angeben Kopplung Code Spring zu vermeiden). Diese Methoden können Sie sicherstellen, dass jede Schnittstelle als ein Feld in der Klasse Instanz angegeben korrekt konfiguriert ist, beim Start, und dann müssen Sie nicht mehr auf null überprüfen Sie Ihre Getter und Setter (vorausgesetzt, Sie erlauben Ihre Singletons Thread-sicher zu bleiben ).

Darüber hinaus ist es viel einfacher, komplexe Initialisierungen mit einem DI-Containern zu tun, anstatt sie selbst zu tun. Zum Beispiel, ich helfen bei der Verwendung von XFire (nicht CeltiXFire verwenden wir nur Java 1.4). Die App verwendet Spring, aber leider XFire der services.xml Konfigurationsmechanismus verwendet. Wenn eine Sammlung von Elementen erforderlich, um festzustellen, dass es hatte null oder mehr Instanzen anstelle von einer oder mehreren Instanzen hatte ich für diesen besonderen Dienst einige der bereitgestellten XFire Code zu überschreiben.

Es gibt bestimmte XFire Standardwerte definiert in seinem Spring-Beans-Schema. Also, wenn wir Frühling wurden unter Verwendung der Dienste zu konfigurieren, die Bohnen verwendet worden sein könnten. Statt dessen, was geschah, war, dass ich eine Instanz einer bestimmten Klasse in der services.xml Datei zu versorgen hatte, anstatt die Bohnen zu verwenden. Um dies zu tun, musste ich den Konstruktor zur Verfügung zu stellen und die Referenzen in der XFire Konfiguration erklärt eingerichtet. Die wirkliche Veränderung, die ich erforderlich machen brauchte, dass ich eine einzige Klasse überlasten.

Aber dank der services.xml Datei hatte ich vier neue Klassen zu erstellen, das Setzen die Standardwerte nach ihren Vorgaben in den Spring-Konfigurationsdateien in ihrem Erbauer. Wenn wir die Spring-Konfiguration verwenden können zu hatten, konnte ich gerade gesagt:

<bean id="base" parent="RootXFireBean">
    <property name="secondProperty" ref="secondBean" />
</bean>

<bean id="secondBean" parent="secondaryXFireBean">
    <property name="firstProperty" ref="thirdBean" />
</bean>

<bean id="thirdBean" parent="thirdXFireBean">
    <property name="secondProperty" ref="myNewBean" />
</bean>

<bean id="myNewBean" class="WowItsActuallyTheCodeThatChanged" />

Stattdessen es sah eher aus wie folgt aus:

public class TheFirstPointlessClass extends SomeXFireClass {
    public TheFirstPointlessClass() {
        setFirstProperty(new TheSecondPointlessClass());
        setSecondProperty(new TheThingThatWasHereBefore());
    }
}

public class TheSecondPointlessClass extends YetAnotherXFireClass {
    public TheSecondPointlessClass() {
        setFirstProperty(TheThirdPointlessClass());
    }
}

public class TheThirdPointlessClass extends GeeAnotherXFireClass {
    public TheThirdPointlessClass() {
        setFirstProperty(new AnotherThingThatWasHereBefore());
        setSecondProperty(new WowItsActuallyTheCodeThatChanged());
    }
}

public class WowItsActuallyTheCodeThatChanged extends TheXFireClassIActuallyCareAbout {
    public WowItsActuallyTheCodeThatChanged() {
    }

    public overrideTheMethod(Object[] arguments) {
        //Do overridden stuff
    }
}

So das Ergebnis ist, dass vier zusätzliche, meist sinnlos Java-Klassen in die Codebasis hinzugefügt werden mußten erreichen die Auswirkungen, die eine zusätzliche Klasse und einige einfache Abhängigkeit Container Informationen erreicht. Dies ist nicht die „Ausnahme, die die Regel bestätigt“, dies ist die Regel ... Macken in Code ist viel saubere Handhabung, wenn die Eigenschaften sind bereits in einem DI-Containern bereitgestellt und Sie sind einfach sie zu ändern eine besondere Situation anzupassen, das passiert öfter als nicht.

Ich habe Ihre Antwort

Es gibt natürlich Kompromisse in jedem Ansatz, aber externalisierte XML-Konfigurationsdateien sind nützlich für die Entwicklung von Unternehmen, in denen Build-Systeme verwendet werden, um den Code zu kompilieren und nicht Ihre IDE. Mit Hilfe des Build-System, sollten Sie bestimmte Werte in den Code injizieren - zum Beispiel der Version des Build (die schmerzhaft sein könnten, um jedes Mal manuell aktualisieren müssen Sie kompilieren). Der Schmerz ist größer, wenn Ihr Build-System Code aus einigem Versionskontrollsystem zieht. Ändern einfache Werte bei der Kompilierung müssten Sie eine Datei ändern, begehen sie, kompilieren und dann jedes Mal für jede Änderung zurück. Dies sind keine Änderungen, die Sie in Ihre Versionskontrolle verpflichten wollen.

Weitere nützliche Anwendungsfälle in Bezug auf die Build-System und externen configs:

  • für verschiedene Stile / Stylesheets für eine einzige Codebasis Injektion baut
  • verschiedene Sätze von dynamischen Inhalten Injektion (oder Verweise auf sie) für Ihre einzigen Code-Basis
  • Injektion Lokalisierungs Kontext für verschiedene Builds / Kunden
  • eine Webservice URI auf einen Backup-Server zu wechseln (wenn der Haupt man geht nach unten)

Update: Alle oben genannten Beispiele waren auf Dinge, die nicht unbedingt haben Abhängigkeiten von Klassen erfordern. Aber Sie können leicht Fälle aufbauen, wo sowohl eine komplexe Aufgabe und Automatisierung erforderlich ist - zum Beispiel:

  • Stellen Sie sich vor, ein System haben, in dem sie den Verkehr auf Ihrer Website überwacht. In Abhängigkeit von der Anzahl der gleichzeitigen Benutzer, stellt sich ein / aus einer Logging-Mechanismus. Vielleicht während des Mechanismus ausgeschaltet ist, ein Stub-Objekt wird an ihrer Stelle setzen.
  • Stellen Sie sich ein Web-Conferencing-System haben, in dem in Abhängigkeit von der Anzahl der Benutzer, die Sie wollen die Möglichkeit, das Gerät, zu tun P2P je nach Anzahl der Teilnehmer

Sie brauchen nicht jedes Mal Ihren Code Sie etwas in der Konfiguration neu kompilieren zu ändern. Es wird Programm Bereitstellung und Wartung vereinfachen. Zum Beispiel können Sie mit nur 1 Änderung in der Konfigurationsdatei eine Komponente mit einem anderen tauschen.

Sie können in einer neuen Implementierung für Freundin Slot. So neu Weibchen können ohne neu zu kompilieren Code injiziert werden.

<bean id="jane" class="foo.bar.HotFemale">
  <property name="age" value="19"/>
</bean>
<bean id="mary" class="foo.bar.Female">
  <property name="age" value="23"/>
</bean>
<bean id="john" class="foo.bar.Male">
  <property name="girlfriend" ref="jane"/>
</bean>

(Die oben geht davon weiblich und HotFemale den gleichen GirlfFriend Schnittstelle implementieren)

In der .NET-Welt, bieten die meisten IoC Frameworks sowohl XML- und Code-Konfiguration.

StructureMap und Ninject zum Beispiel verwendet fließend Schnittstellen Container zu konfigurieren. Sie sind nicht mehr eingeschränkt XML-Konfigurationsdateien zu verwenden. Spring, die auch in .NET vorhanden ist, stützt sich stark auf XML-Dateien, da es seine historische Hauptkonfigurationsoberfläche ist, aber es ist immer noch möglich, Behälter programmatisch zu konfigurieren.

Einfache die Kombination von Teilkonfigurationen in eine endgültige vollständige Konfiguration.

Zum Beispiel in Web-Anwendungen, das Modell, Ansicht und Controller werden in der Regel in separaten Konfigurationsdateien angegeben. Verwenden Sie den deklarativen Ansatz, können Sie laden, zum Beispiel:

  UI-context.xml
  Model-context.xml
  Controller-context.xml

oder laden Sie mit einem anderen UI und ein paar zusätzlichen Controller:

  AlternateUI-context.xml
  Model-context.xml
  Controller-context.xml
  ControllerAdditions-context.xml

Um in Code das gleiche tun erfordert eine Infrastruktur für die Kombination von Teilkonfigurationen. Nicht unmöglich, in Code zu tun, aber sicherlich einfacher zu machen, einen IoC-Framework verwendet wird.

Oft der wichtige Punkt ist , die ändert die Konfiguration, nachdem das Programm geschrieben wurde. Mit Konfiguration im Code annehmen, dass Sie implizit diese Person ändert es die gleichen Fähigkeiten und Zugriff auf den Quellcode etc hat wie der ursprüngliche Autor hatte.

In Produktionssystemen ist es sehr praktisch eine Teilmenge von Einstellungen zu extrahieren (z Alter in ihrem Beispiel) zu XML-Datei und erlaubt zum Beispiel Systemadministrator oder Support-Personal, ohne den Wert zu ändern, um sie um die volle Leistung über Quellcode oder andere Einstellungen zu geben -. oder einfach nur um sie von Komplexität zu isolieren

Von einem Frühling perspecitve ich Ihnen zwei Antworten geben kann.

Zuerst wird die XML-Konfiguration ist nicht der einzige Weg, um die Konfiguration zu definieren. Die meisten Dinge können so konfiguriert werden Annotationen verwenden und die Dinge, die mit XML sind Konfiguration für Code getan werden muss, die Sie sowieso nicht schreiben, wie ein Verbindungspool, die Sie aus einer Bibliothek verwenden. Feder 3 umfasst ein Verfahren zum Definieren der DI-Konfiguration mit Hilfe von Java ähnlich die Hand gerollt DI-Konfiguration in Ihrem Beispiel. So Frühling mit nicht bedeutet, dass Sie eine XML-basierte Konfigurationsdatei verwenden.

Zum zweiten Frühling ist viel mehr als nur ein DI-Framework. Es hat viele weitere Funktionen, darunter Transaktionsmanagement und AOP. Die Spring-XML-Konfiguration mischt all diese Konzepte zusammen. Oft in der gleichen Konfigurationsdatei bin Angabe I Bean Abhängigkeiten, Transaktionseinstellungen und das Hinzufügen von Session Beans scoped, die tatsächlich mit AOP im Hintergrund behandelt. Ich finde die XML-Konfiguration zu einem besseren Ort bietet all diese Funktionen zu verwalten. Ich glaube auch, dass die Annotation-basierte Konfiguration und XML-Konfiguration skalieren besser als Java-basierte Konfiguration zu tun.

Aber ich Ihren Punkt sehen, und es ist nichts falsch mit der Dependency Injection-Konfiguration in Java definieren. Ich normalerweise, dass ich in Unit-Tests und wenn ich an einem Projekt klein genug, um gerade arbeite, dass ich keinen DI Rahmen hinzugefügt. Ich normalerweise nicht Konfiguration in Java angeben, da mir das ist die Art Sanitär-Code, den ich versuche, um weg von zu schreiben, als ich entschied Frühling zu verwenden. Das ist ein Vorzug aber es bedeutet nicht, dass XML-Konfiguration Java-basierte Konfiguration überlegen ist.

Frühling hat auch einen Immobilien-Loader. Wir verwenden diese Methode Variablen zu setzen, die von der Umgebung abhängig sind (beispielsweise Entwicklung, Prüfung, Abnahme, Produktion, ...). Dies könnte zum Beispiel die Warteschlange zu hören.

Wenn es keinen Grund gibt, warum die Eigenschaft würde sich ändern, gibt es auch keinen Grund, es auf diese Weise zu konfigurieren.

Ihr Fall ist sehr einfach und daher keine IoC (Inversion of Control) Container wie Spring benötigt. Auf der anderen Seite, wenn Sie auf „Programm-Schnittstellen, nicht Implementierungen“ (was eine gute Praxis in OOP ist), können Sie Code wie folgt aussehen:

IService myService;
// ...
public void doSomething() {
  myService.fetchData();
}

(beachten Sie, dass die Art der myService ist IService - eine Schnittstelle, nicht eine konkrete Implementierung). Nun kann es nützlich sein, Ihre IoC-Container automatisch die richtige konkrete Instanz IService während der Initialisierung liefern zu lassen - wenn Sie viele Schnittstellen und viele Implementierungen haben, kann es mühsam sein, von Hand zu tun. Die wichtigsten Vorteile eines IoC-Container (Dependency Injection-Framework) sind:

  • Externe Konfiguration Zuordnung zwischen Schnittstellen und den konkreten Implementierungen
  • IoC-Container behandelt einige heikle Themen wie kompliziert Abhängigkeitsgraphen zu lösen, Komponente Lebensdauer Verwaltung etc.
  • Sie sparen Codierung Zeit, weil Sie Zuordnungen deklarativ bieten, nicht in einem prozeduralen Code
  • Invertierung Prinzip Steuerung ermöglicht einen einfachen Unit-Tests, weil Sie echte Implementierungen mit gefälschten ersetzen können (wie SQL-Datenbank zu ersetzen mit einem In-Memory-one)

in einer XML-Konfigurationsdatei initialisiert wird Ihren Debugging / Anpassung der Arbeit mit einem Kunden vereinfachen, die Ihre App auf ihren Computern eingesetzt hat. (Da es nicht erforderlich ist Neuübersetzung + Binärdateien Ersatz)

Einer der attraktivsten Gründe dafür ist die „ Hollywood Prinzip “: nicht nennen uns, wir rufen Sie an. Eine Komponente ist nicht erforderlich, um die Abfragen zu anderen Komponenten zu tun und Dienstleistungen selbst; stattdessen werden sie automatisch zur Verfügung gestellt. In Java bedeutet dies, dass es nicht mehr notwendig ist JNDI Lookups innerhalb der Komponente zu tun.

Es ist auch viel einfacher zu Unit-Test eine Komponente in Isolation: Statt es eine tatsächliche Implementierung der Komponenten des Gebens es braucht, geben Sie einfach zu verwenden (möglicherweise automatisch generiert) verspottet

.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top