Was ist Abhängigkeitsinjektion und Inversion der Kontrolle in Spring Framework?


111

"Dependency Injection" und "Inversion of Control" werden häufig als Hauptvorteile der Verwendung des Spring-Frameworks für die Entwicklung von Web-Frameworks genannt

Könnte jemand mit einem Beispiel erklären, was es ist, wenn möglich in sehr einfachen Worten?



3
@SteveChambers ist kein Duplikat, diese Frage wird in Springs Perspective gestellt. Diese Frage ist allgemein vorausschauend.
VdeX

Antworten:


233
  • Spring hilft bei der Erstellung lose gekoppelter Anwendungen aufgrund von Dependency Injection .
  • Im Frühjahr definieren Objekte ihre Zuordnungen (Abhängigkeiten) und machen sich keine Gedanken darüber, wie sie diese Abhängigkeiten erhalten . Es liegt in der Verantwortung von Spring, die erforderlichen Abhängigkeiten zum Erstellen von Objekten bereitzustellen.

Beispiel : Angenommen, wir haben ein Objekt Employeeund es hängt vom Objekt ab Address. Wir würden eine entsprechende Bean Employeedefinieren, die ihre Abhängigkeit vom Objekt definiert Address.

Wenn Spring versucht, ein EmployeeObjekt zu erstellen , wird festgestellt, dass Employeeeine Abhängigkeit von vorhanden Addressist. Daher wird zuerst das AddressObjekt (abhängiges Objekt) erstellt und dann in das EmployeeObjekt eingefügt.

  • Inversion of Control ( IoC ) und Dependency Injection ( DI ) werden synonym verwendet. IoC wird durch DI erreicht. DI ist der Prozess der Bereitstellung der Abhängigkeiten und IoC ist das Endergebnis von DI. ( Hinweis: DI ist nicht der einzige Weg, um IoC zu erreichen. Es gibt auch andere Wege .)

  • Durch DI wird die Verantwortung für das Erstellen von Objekten von unserem Anwendungscode auf den Spring-Container verlagert. Dieses Phänomen wird IoC genannt.

  • Die Abhängigkeitsinjektion kann durch Setterinjektion oder Konstruktorinjektion erfolgen.

Ich bin nicht einverstanden. Ich denke nicht, dass dies eine klare Erklärung ist. Warum können Sie nicht einfach "Adresse" in "Mitarbeiter" instanziieren, anstatt ein Framework zu erhalten, um es zu erstellen und zu injizieren? Ein etwas detaillierteres Beispiel ist erforderlich.
Boris

2
@Boris Niemand hat gesagt, dass Sie Ihre eigenen Objekte nicht instanziieren können. Der einzige Zweck der Antwort bestand darin, zu demonstrieren, wie Sie mit DI dasselbe erreichen können. Sie können sowohl DI als auch Objekte durch Client-Code instanziieren lassen. Dies würde zumindest teilweise immer noch als IOC bezeichnet.
Bogdan.rusu


Boris. Sehr neidisch? Das ist die beste Antwort aller Zeiten.
Aniket Kapse

31

Ich werde mein einfaches Verständnis dieser beiden Begriffe aufschreiben: (Zum schnellen Verständnis lesen Sie einfach Beispiele)

  • Abhängigkeitsinjektion (DI):
    Abhängigkeitsinjektion bedeutet im Allgemeinen, dass ein abhängiges Objekt als Parameter an eine Methode übergeben wird, anstatt dass die Methode das abhängige Objekt erstellt .
    In der Praxis bedeutet dies, dass die Methode nicht direkt von einer bestimmten Implementierung abhängig ist. Jede Implementierung, die die Anforderungen erfüllt, kann als Parameter übergeben werden.

    Mit dieser Implementierung von Objekten werden ihre Abhängigkeiten definiert. Und der Frühling macht es verfügbar.
    Dies führt zu einer lose gekoppelten Anwendungsentwicklung.

    Kurzes Beispiel: MITARBEITEROBJEKT BEI ERSTELLUNG ERSTELLT ES AUTOMATISCH EIN ADRESSOBJEKT (wenn die Adresse als Abhängigkeit durch das Mitarbeiterobjekt definiert ist) *.

  • IoC-Container (Inversion of Control):
    Dies ist ein gemeinsames Merkmal von Frameworks. IoC verwaltet Java-Objekte
    - von der Instanziierung bis zur Zerstörung über seine BeanFactory.
    - Java-Komponenten, die vom IoC-Container instanziiert werden, werden als Beans bezeichnet. Der IoC-Container verwaltet den Umfang, die Lebenszyklusereignisse und alle AOP-Funktionen eines Beans, für die er konfiguriert und codiert wurde.

    QUICK EXAMPLE:Inversion of Control is about getting freedom, more flexibility, and less dependency. When you are using a desktop computer, you are slaved (or say, controlled). You have to sit before a screen and look at it. Using keyboard to type and using mouse to navigate. And a bad written software can slave you even more. If you replaced your desktop with a laptop, then you somewhat inverted control. You can easily take it and move around. So now you can control where you are with your computer, instead of computer controlling it.

    Durch die Implementierung von Inversion of Control erhält ein Software- / Objektkonsument mehr Steuerelemente / Optionen für die Software / Objekte, anstatt gesteuert zu werden oder weniger Optionen zu haben.

    Die Umkehrung der Steuerung als Entwurfsrichtlinie dient folgenden Zwecken:
    - Es erfolgt eine Entkopplung der Ausführung einer bestimmten Aufgabe von der Implementierung.
    - Jedes Modul kann sich auf das konzentrieren, wofür es entwickelt wurde.
    - Module machen keine Annahmen darüber, was andere Systeme tun, sondern verlassen sich auf ihre Verträge.
    - Das Ersetzen von Modulen hat keine Nebenwirkungen auf andere Module

Ich werde die Dinge hier abstrakt halten. Sie können die folgenden Links besuchen, um ein detailliertes Verständnis des Themas zu erhalten.

Eine gute Lektüre mit Beispiel

Ausführliche Erklärung


11

In Spring werden Objekte lose gekoppelt, dh jede Klasse ist unabhängig voneinander, so dass alles einzeln getestet werden kann. Bei Verwendung dieser Klassen kann eine Klasse jedoch von anderen Klassen abhängig sein, die zuerst instanziiert werden müssen.

Wir sagen Spring also, dass Klasse A von Klasse B abhängig ist. Wenn Sie also eine Bean (wie eine Klasse) für Klasse A erstellen, instanziiert sie Klasse B vor der Klasse A und injiziert diese in Klasse A mit Setter- oder Konstruktor-DI-Methoden. Das heißt, wir erzählen dem Frühling die Abhängigkeit zur Laufzeit. Das ist DI.

Da wir die Verantwortung für das Erstellen von Objekten (Beans), deren Verwaltung und deren Aggregationen Spring zuweisen, anstatt sie fest zu codieren, nennen wir sie Inversion Of Control (IOC).


7

Inversion of Control (IOC):

IoC ist ein Entwurfsmuster, das das Invertieren des Steuerungsflusses in einem System beschreibt, sodass der Ausführungsfluss nicht durch einen zentralen Code gesteuert wird. Dies bedeutet, dass Komponenten nur von Abstraktionen anderer Komponenten abhängen sollten und nicht für die Erstellung abhängiger Objekte verantwortlich sind. Stattdessen werden Objektinstanzen zur Laufzeit von einem IoC-Container über Dependency Injection (DI) bereitgestellt.

IoC ermöglicht ein besseres Software-Design, das die Wiederverwendung, lose Kopplung und das einfache Testen von Softwarekomponenten erleichtert.

Abhängigkeitsinjektion (DI):

DI ist eine Technik zum Übergeben von Abhängigkeiten an den Konstruktor eines Objekts. Wenn das Objekt aus dem Container geladen wurde, werden seine Abhängigkeiten automatisch vom Container bereitgestellt. Auf diese Weise können Sie eine Abhängigkeit verwenden, ohne manuell eine Instanz erstellen zu müssen. Dies reduziert die Kopplung und gibt Ihnen eine bessere Kontrolle über die Lebensdauer von Objektinstanzen.

Klicken Sie hier, um weitere Informationen anzuzeigen


6

Frühling: Frühling ist der Container "Inversion of Control" für die Java-Plattform.

Inversion of Control (IoC): Inversion of Control (IoC) ist eine objektorientierte Programmierpraxis, bei der die Objektkopplung zur Laufzeit durch ein "Assembler" -Objekt begrenzt wird und zur Kompilierungszeit normalerweise nicht mithilfe einer statischen Analyse erkennbar ist.

Dependency Injection (DI): "Dependency Injection ist ein Software-Design-Muster, mit dem fest codierte Abhängigkeiten entfernt und zur Laufzeit oder zur Kompilierung geändert werden können." -wiki.


Wie ist das einfacher als das, was es bereits gibt (woher stammt diese Antwort)? Die Forderung des OP nach Einfachheit wird nicht berücksichtigt, es sei denn, die doppelten Zitate um Terminologien machen die Dinge auf magische Weise einfacher.
Flamme von Udun

6

Umkehrung der Steuerung - Dies bedeutet, dass die Kontrolle über das Erstellen und Instanziieren der Spring Beans im Spring IOC-Container übertragen wird. Die einzige Aufgabe des Entwicklers besteht darin, die Beans in der Spring XML-Datei zu konfigurieren.

Abhängigkeitsspritze-

Betrachten Sie eine Klasse Mitarbeiter

class Employee { 
   private int id;
   private String name;
   private Address address;

   Employee() {
     id = 10;
     name="name";
     address = new Address();
   }


}

und Klassenadresse berücksichtigen

class Address {
   private String street;
   private String city;

   Address() {
     street="test";
     city="test1";

  }
}

Im obigen Code werden die Adressklassenwerte nur festgelegt, wenn die Employee-Klasse instanziiert wird. Dies ist die Abhängigkeit der Adressklasse von der Employee-Klasse. Und Spring löst dieses Problem mithilfe des Abhängigkeitsinjektionskonzepts, indem zwei Möglichkeiten zum Injizieren dieser Abhängigkeit bereitgestellt werden.

  1. Setter-Injektion

Setter-Methode in der Employee-Klasse, die eine Referenz der Address-Klasse verwendet

public void setAddress(Address addr) {
    this.address = addr;
}
  1. Konstruktorinjektion

Konstruktor in der Employee-Klasse, der die Adresse akzeptiert

Employee(Address addr) {
      this.address = addr;
}

Auf diese Weise können die Adressklassenwerte unabhängig voneinander mit einer Setter- / Konstruktorinjektion festgelegt werden.


3

Inversion of Control ist ein generisches Entwurfsprinzip der Softwarearchitektur, mit dessen Hilfe wiederverwendbare, modulare Software-Frameworks erstellt werden können, die einfach zu warten sind.

Es ist ein Entwurfsprinzip, bei dem der Kontrollfluss von der generisch geschriebenen Bibliothek oder dem wiederverwendbaren Code "empfangen" wird.

Um es besser zu verstehen, sehen wir uns an, wie wir in unseren früheren Codierungstagen codiert haben. In prozeduralen / traditionellen Sprachen steuert die Geschäftslogik im Allgemeinen den Fluss der Anwendung und "ruft" den generischen oder wiederverwendbaren Code / die Funktionen auf. In einer einfachen Konsolenanwendung wird mein Steuerungsfluss beispielsweise durch die Anweisungen meines Programms gesteuert, die möglicherweise die Aufrufe einiger allgemein wiederverwendbarer Funktionen umfassen.

print ("Please enter your name:");
scan (&name);
print ("Please enter your DOB:");
scan (&dob);

//More print and scan statements
<Do Something Interesting>

//Call a Library function to find the age (common code)
print Age

Im Gegensatz dazu sind bei IoC die Frameworks der wiederverwendbare Code, der die Geschäftslogik "aufruft".

In einem Windows-basierten System ist beispielsweise bereits ein Framework zum Erstellen von UI-Elementen wie Schaltflächen, Menüs, Fenstern und Dialogfeldern verfügbar. Wenn ich die Geschäftslogik meiner Anwendung schreibe, werden die Ereignisse des Frameworks meinen Geschäftslogikcode aufrufen (wenn ein Ereignis ausgelöst wird) und NICHT das Gegenteil.

Obwohl der Code des Frameworks meine Geschäftslogik nicht kennt, kann er meinen Code trotzdem aufrufen. Dies wird durch Ereignisse / Delegaten, Rückrufe usw. erreicht. Hier ist die Steuerung des Flusses "invertiert".

Anstatt den Kontrollfluss von statisch gebundenen Objekten abhängig zu machen, hängt der Fluss vom Gesamtobjektgraphen und den Beziehungen zwischen verschiedenen Objekten ab.

Die Abhängigkeitsinjektion ist ein Entwurfsmuster, das das IoC-Prinzip zum Auflösen von Abhängigkeiten von Objekten implementiert.

In einfacheren Worten, wenn Sie versuchen, Code zu schreiben, erstellen und verwenden Sie verschiedene Klassen. Eine Klasse (Klasse A) kann andere Klassen (Klasse B und / oder D) verwenden. Klasse B und D sind also Abhängigkeiten der Klasse A.

Eine einfache Analogie wird ein Klassenauto sein. Ein Auto kann von anderen Klassen wie Motor, Reifen und mehr abhängen.

Die Abhängigkeitsinjektion schlägt vor, dass anstelle der abhängigen Klassen (hier Class Car), die ihre Abhängigkeiten erstellen (Class Engine und Klasse Tire), der Klasse die konkrete Instanz der Abhängigkeit injiziert werden sollte.

Lassen Sie uns mit einem praktischeren Beispiel verstehen. Bedenken Sie, dass Sie Ihren eigenen TextEditor schreiben. Unter anderem können Sie eine Rechtschreibprüfung durchführen, mit der der Benutzer die Tippfehler in seinem Text überprüfen kann. Eine einfache Implementierung eines solchen Codes kann sein:

Class TextEditor
{

    //Lot of rocket science to create the Editor goes here

    EnglishSpellChecker objSpellCheck;
    String text;

    public void TextEditor()

    {   

        objSpellCheck = new EnglishSpellChecker();

    }

    public ArrayList <typos> CheckSpellings()
    {

        //return Typos;

    }

}

Auf den ersten Blick sieht alles rosig aus. Der Benutzer wird Text schreiben. Der Entwickler erfasst den Text, ruft die CheckSpellings-Funktion auf und findet eine Liste der Tippfehler, die er dem Benutzer anzeigt.

Alles scheint gut zu funktionieren, bis ein Benutzer eines schönen Tages anfängt, Französisch im Editor zu schreiben.

Um mehr Sprachen unterstützen zu können, benötigen wir mehr SpellChecker. Wahrscheinlich Französisch, Deutsch, Spanisch usw.

Hier haben wir einen eng gekoppelten Code erstellt, wobei "English" SpellChecker eng mit unserer TextEditor-Klasse gekoppelt ist. Dies bedeutet, dass unsere TextEditor-Klasse vom EnglishSpellChecker abhängig ist oder mit anderen Worten, EnglishSpellCheker ist die Abhängigkeit für TextEditor. Wir müssen diese Abhängigkeit entfernen. Darüber hinaus benötigt unser Texteditor eine Möglichkeit, die konkrete Referenz einer Rechtschreibprüfung nach Ermessen des Entwicklers zur Laufzeit zu speichern.

Wie wir in der Einführung von DI gesehen haben, schlägt es vor, dass die Klasse mit ihren Abhängigkeiten injiziert werden sollte. Es sollte also in der Verantwortung des aufrufenden Codes liegen, alle Abhängigkeiten in die aufgerufene Klasse / den aufgerufenen Code einzufügen. So können wir unseren Code als umstrukturieren

interface ISpellChecker
{

    Arraylist<typos> CheckSpelling(string Text);

}

Class EnglishSpellChecker : ISpellChecker

{

    public override Arraylist<typos> CheckSpelling(string Text)

    {

        //All Magic goes here.

    }

}



Class FrenchSpellChecker : ISpellChecker

{

    public override Arraylist<typos> CheckSpelling(string Text)

    {

        //All Magic goes here.

    }

}

In unserem Beispiel sollte die TextEditor-Klasse die konkrete Instanz des ISpellChecker-Typs erhalten.

Jetzt kann die Abhängigkeit in einen Konstruktor, eine öffentliche Eigenschaft oder eine Methode eingefügt werden.

Versuchen wir, unsere Klasse mit Constructor DI zu ändern. Die geänderte TextEditor-Klasse sieht ungefähr so ​​aus:

Class TextEditor

{

    ISpellChecker objSpellChecker;

    string Text;



    public void TextEditor(ISpellChecker objSC)

    {

        objSpellChecker = objSC;

    }



    public ArrayList <typos> CheckSpellings()

    {

        return objSpellChecker.CheckSpelling();

    }

}

Damit der aufrufende Code beim Erstellen des Texteditors den entsprechenden SpellChecker-Typ in die Instanz des TextEditors einfügen kann.

Den vollständigen Artikel können Sie hier lesen


1

Die traditionelle Methode zum Abrufen der Adressinstanz in Employee besteht darin, eine neue Instanz der Adressklasse zu erstellen. Spring erstellt alle abhängigen Objekte für uns, sodass wir uns nicht um Objekte kümmern müssen.

Im Frühjahr sind wir also nur auf den Federcontainer angewiesen, der uns das Abhängigkeitsobjekt liefert.


1

IOC ist eine Technik, bei der Sie jemand anderem erlauben, das Objekt für Sie zu erstellen. Und die andere Person im Falle eines Frühlings ist der IOC-Container.

Die Abhängigkeitsinjektion ist eine Technik, bei der ein Objekt die Abhängigkeit eines anderen Objekts liefert.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.