3581 Stimmen

Was ist Dependency Injection?

Es wurden bereits mehrere Fragen zu folgenden Themen gestellt Dependency Injection wie z. B. wann sie zu verwenden ist und welche Rahmenbedingungen es dafür gibt. Wie auch immer,

Was ist Dependency Injection und wann und warum sollte sie eingesetzt werden?

0 Stimmen

Siehe meine Diskussion über Dependency Injection Hier .

44 Stimmen

Ich stimme den Kommentaren zu den Links zu. Ich kann verstehen, dass Sie vielleicht auf jemand anderen verweisen wollen. Aber fügen Sie zumindest hinzu, warum Sie sie verlinken und was diesen Link besser macht als die anderen Links, die ich mit Google finden könnte

0 Stimmen

@AR: Technisch gesehen, ist Dependency Injection no eine besondere Form von IoC. Vielmehr ist IoC eine Technik, die zur Bereitstellung von Dependency Injection verwendet wird. Es können auch andere Techniken für die Dependency Injection verwendet werden (obwohl IoC die einzige ist, die häufig verwendet wird), und IoC wird auch für viele andere Probleme verwendet.

15voto

Anwar Husain Punkte 797

Die beste Analogie, die mir einfällt, ist der Chirurg und sein(e) Assistent(en) in einem Operationssaal, in dem der Chirurg die Hauptperson ist und sein Assistent die verschiedenen chirurgischen Komponenten bereitstellt, wenn er sie braucht, so dass sich der Chirurg auf das konzentrieren kann, was er am besten kann (die Operation). Ohne den Assistenten muss der Chirurg die Komponenten jedes Mal selbst besorgen, wenn er sie braucht.

DI ist eine Technik, die den Komponenten die übliche zusätzliche Verantwortung (Last) abnimmt, die abhängigen Komponenten zu holen, indem man sie ihnen zur Verfügung stellt.

DI bringt Sie näher an das Prinzip der einzigen Verantwortung (SR) heran, wie die surgeon who can concentrate on surgery .

Wann sollte man DI verwenden: Ich würde empfehlen, DI in fast allen Produktionsprojekten (klein/groß) zu verwenden, insbesondere in sich ständig verändernden Geschäftsumgebungen :)

Warum: Weil Sie möchten, dass Ihr Code leicht testbar ist, mit Mocks versehen werden kann usw., damit Sie Ihre Änderungen schnell testen und auf den Markt bringen können. Und warum auch nicht, wenn es viele tolle kostenlose Tools/Frameworks gibt, die Sie auf Ihrem Weg zu einer Codebasis unterstützen, bei der Sie mehr Kontrolle haben.

0 Stimmen

@WindRider Danke. Ich kann nicht mehr zustimmen. Das menschliche Leben und der menschliche Körper sind großartige Beispiele für exzellentes Design... die Wirbelsäule ist ein hervorragendes Beispiel für ein ESB :)...

14voto

Piyush Deshpande Punkte 195

Das bedeutet, dass Objekte nur so viele Abhängigkeiten haben sollten, wie für die Erfüllung ihrer Aufgabe erforderlich sind, und dass die Abhängigkeiten gering sein sollten. Außerdem sollten die Abhängigkeiten eines Objekts nach Möglichkeit von Schnittstellen und nicht von "konkreten" Objekten bestehen. (Ein konkretes Objekt ist jedes Objekt, das mit dem Schlüsselwort new erstellt wird.) Lose Kopplung fördert die Wiederverwendbarkeit, erleichtert die Wartung und ermöglicht es Ihnen, anstelle von teuren Diensten einfach "Scheinobjekte" bereitzustellen.

Die "Dependency Injection" (DI), auch bekannt als "Inversion of Control" (IoC), kann als eine Technik zur Förderung dieser losen Kopplung verwendet werden.

Es gibt zwei Hauptansätze für die Implementierung von DI:

  1. Injektion des Konstruktors
  2. Setter-Injektion

Injektion des Konstruktors

Es ist die Technik der Übergabe von Abhängigkeiten von Objekten an ihren Konstruktor.

Beachten Sie, dass der Konstruktor eine Schnittstelle und kein konkretes Objekt annimmt. Beachten Sie auch, dass eine Ausnahme ausgelöst wird, wenn der Parameter orderDao null ist. Dies unterstreicht, wie wichtig es ist, eine gültige Abhängigkeit zu erhalten. Constructor Injection ist meiner Meinung nach der bevorzugte Mechanismus, um einem Objekt seine Abhängigkeiten zu geben. Dem Entwickler ist beim Aufruf des Objekts klar, welche Abhängigkeiten dem Objekt "Person" zur ordnungsgemäßen Ausführung übergeben werden müssen.

Setzer Injektion

Aber betrachten Sie das folgende Beispiel Angenommen, Sie haben eine Klasse mit zehn Methoden, die keine Abhängigkeiten haben, aber Sie fügen eine neue Methode hinzu, die eine Abhängigkeit von IDAO hat. Sie könnten den Konstruktor ändern, um Constructor Injection zu verwenden, aber das könnte Sie dazu zwingen, alle Konstruktoraufrufe überall zu ändern. Alternativ könnte man auch einfach einen neuen Konstruktor hinzufügen, der die Abhängigkeit übernimmt, aber wie soll ein Entwickler dann wissen, wann er den einen Konstruktor dem anderen vorziehen soll? Wenn die Erstellung der Abhängigkeit sehr teuer ist, warum sollte sie dann erstellt und an den Konstruktor übergeben werden, wenn sie nur selten verwendet wird? "Setter Injection" ist eine weitere DI-Technik, die in Situationen wie dieser eingesetzt werden kann.

Setter Injection erzwingt keine Übergabe von Abhängigkeiten an den Konstruktor. Stattdessen werden die Abhängigkeiten auf öffentliche Eigenschaften gesetzt, die das benötigte Objekt aufweist. Wie bereits angedeutet, sind die primären Beweggründe für diese Vorgehensweise folgende:

  1. Unterstützung von Dependency Injection, ohne den Konstruktor einer Legacy-Klasse ändern zu müssen.
  2. Teure Ressourcen oder Dienste werden so spät wie möglich und nur bei Bedarf geschaffen.

Hier ist ein Beispiel dafür, wie der obige Code aussehen würde:

public class Person {
    public Person() {}

    public IDAO Address {
        set { addressdao = value; }
        get {
            if (addressdao == null)
              throw new MemberAccessException("addressdao" +
                             " has not been initialized");
            return addressdao;
        }
    }

    public Address GetAddress() {
       // ... code that uses the addressdao object
       // to fetch address details from the datasource ...
    }

    // Should not be called directly;
    // use the public property instead
    private IDAO addressdao;

3 Stimmen

Ich denke, dass Ihr erster Absatz von der Frage abweicht und überhaupt nicht der Definition von DI entspricht (d.h. Sie versuchen, SOLID und nicht DI zu definieren). Technisch gesehen können Sie auch bei 100 Abhängigkeiten noch Dependency Injection verwenden. Ebenso ist es möglich, konkrete Abhängigkeiten zu injizieren - es ist immer noch dependency injection.

11voto

Alex Punkte 5791

Ich weiß, dass es bereits viele Antworten gibt, aber ich fand dies sehr hilfreich: http://tutorials.jenkov.com/dependency-injection/index.html

Keine Abhängigkeit:

public class MyDao {

  protected DataSource dataSource = new DataSourceImpl(
    "driver", "url", "user", "password");

  //data access methods...
  public Person readPerson(int primaryKey) {...}     
}

Abhängigkeit:

public class MyDao {

  protected DataSource dataSource = null;

  public MyDao(String driver, String url, String user, String password) {
    this.dataSource = new DataSourceImpl(driver, url, user, password);
  }

  //data access methods...
  public Person readPerson(int primaryKey) {...}
}

Beachten Sie, wie die DataSourceImpl Instanziierung in einen Konstruktor verschoben wird. Der Konstruktor nimmt vier Parameter entgegen, die die vier Werte sind, die von der DataSourceImpl . Auch wenn die MyDao Klasse immer noch von diesen vier Werten abhängt, erfüllt sie diese Abhängigkeiten nicht mehr selbst. Sie werden von der Klasse bereitgestellt, die eine MyDao Instanz.

2 Stimmen

Würde DI Sie nicht durch Schnittstelle Ihre DataSourceImp bereits konstruiert passieren?

10voto

Ich denke, da jeder für DI geschrieben hat, möchte ich ein paar Fragen stellen.

  1. Wenn Sie eine Konfiguration von DI haben, wo alle tatsächlichen Implementierungen (nicht Schnittstellen), die in eine Klasse (z. B. Dienste zu einem Controller) injiziert werden, warum ist das nicht eine Art von Hard-Coding?
  2. Was ist, wenn ich das Objekt zur Laufzeit ändern möchte? Zum Beispiel, meine Konfiguration sagt bereits, wenn ich MyController instanziieren, injizieren für FileLogger als ILogger. Aber ich möchte vielleicht DatabaseLogger injizieren.
  3. Jedes Mal, wenn ich ändern möchte, welche Objekte meine AClass benötigt, muss ich nun an zwei Stellen nachsehen - in der Klasse selbst und in der Konfigurationsdatei. Wie kann das das Leben einfacher machen?
  4. Wenn Aproperty von AClass nicht injiziert wird, ist es dann schwieriger, es auszuspotten?
  5. Um auf die erste Frage zurückzukommen. Wenn die Verwendung von new object() schlecht ist, wieso injizieren wir dann die Implementierung und nicht die Schnittstelle? Ich denke, viele von Ihnen sagen, dass wir tatsächlich die Schnittstelle injizieren, aber die Konfiguration macht Sie die Implementierung dieser Schnittstelle angeben nicht zur Laufzeit es ist während der Kompilierungszeit hart kodiert.

Dies basiert auf der Antwort von @Adam N.

Warum muss sich der PersonService nicht mehr um den GroupMembershipService kümmern? Sie haben gerade erwähnt, dass GroupMembership mehrere Dinge (Objekte/Eigenschaften) hat, von denen es abhängt. Wenn GMService in PService erforderlich war, würden Sie es als eine Eigenschaft haben. Sie können mock, dass aus unabhängig davon, ob Sie es injiziert oder nicht. Der einzige Fall, in dem ich es injiziert haben möchte, ist, wenn GMService spezifischere Unterklassen hat, was Sie erst zur Laufzeit wissen würden. Dann würde man die Unterklasse injizieren wollen. Oder wenn man sie entweder als Singleton oder als Prototyp verwenden möchte. Um ehrlich zu sein, ist in der Konfigurationsdatei alles hart kodiert, was die Unterklasse eines Typs (Schnittstelle) betrifft, die während der Kompilierungszeit injiziert wird.

EDITAR

Ein netter Kommentar von Jose Maria Arranz auf DI

DI erhöht die Kohäsion, da es nicht mehr notwendig ist, die Richtung der Abhängigkeit zu bestimmen und Glue-Code zu schreiben.

Falsch. Die Richtung der Abhängigkeiten ist in XML-Form oder als Anmerkungen, Ihre Abhängigkeiten sind als XML-Code und Anmerkungen geschrieben. XML und Annotationen SIND Quellcode.

DI reduziert die Kopplung, indem alle Komponenten modular (d.h. austauschbar) sind und über klar definierte Schnittstellen zueinander verfügen.

Falsch. Sie benötigen kein DI-Framework, um einen modularen, auf Schnittstellen basierenden Code zu erstellen.

Zum Thema ersetzbar: Mit einem sehr einfachen .properties-Archiv und Class.forName können Sie festlegen, welche Klassen geändert werden können. Wenn JEDE Klasse Ihres Codes geändert werden kann, ist Java nichts für Sie, verwenden Sie eine Skriptsprache. Übrigens: Annotationen können nicht ohne Neukompilierung geändert werden.

Meiner Meinung nach gibt es nur einen Grund für DI-Rahmen: Kesselplattenreduzierung. Mit einem gut gemachten Fabriksystem können Sie das gleiche tun, kontrollierter und vorhersehbarer als Ihr bevorzugtes DI-Framework, DI-Frameworks versprechen Code-Reduzierung (XML und Annotationen sind auch Quellcode). Das Problem ist, dass diese Reduktion nur in sehr einfachen Fällen möglich ist (eine Instanz pro Klasse und ähnliches). In der realen Welt ist es manchmal nicht so einfach, das passende Serviceobjekt zu finden, indem man eine Klasse auf ein Singleton-Objekt abbildet.

9voto

Nikos M. Punkte 7365

Injektion von Abhängigkeiten bedeutet einen Weg (eigentlich wie auch immer ), damit ein Teil des Codes (z. B. eine Klasse) modular auf Abhängigkeiten (andere Teile des Codes, z. B. andere Klassen, von denen er abhängt) zugreifen kann, ohne dass diese fest einkodiert sind (so dass sie sich ändern oder überschrieben werden können oder sogar zu einem anderen Zeitpunkt geladen werden können, je nach Bedarf)

(und ps, ja, es ist ein übermäßig gehypter 25$-Name für ein ziemlich einfaches Konzept geworden) mein .25 Cents

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X