Co to jest Dependency Injection i Inversion of Control w Spring Framework?

112

„Wstrzykiwanie zależności” i „Odwrócenie kontroli” są często wymieniane jako główne zalety używania frameworka Spring do tworzenia frameworków internetowych

Czy ktoś mógłby wyjaśnić, co to jest w bardzo prostych słowach, na przykładzie, jeśli to możliwe?

Chillax
źródło
możliwy duplikat What is Inversion of Control?
Steve Chambers
3
@SteveChambers to nie duplikat, to pytanie jest zadawane w perspektywie Springs. To pytanie ma charakter ogólny.
VdeX

Odpowiedzi:

233
  • Spring pomaga w tworzeniu luźno powiązanych aplikacji ze względu na Dependency Injection .
  • Wiosną obiekty definiują swoje skojarzenia (zależności) i nie przejmują się tym, w jaki sposób otrzymają te zależności . Za zapewnienie wymaganych zależności do tworzenia obiektów odpowiada Spring.

Na przykład : Załóżmy, że mamy obiekt Employeei jest on zależny od obiektu Address. Zdefiniowalibyśmy ziarno odpowiadające temu Employee, które zdefiniuje jego zależność od obiektu Address.

Kiedy Spring spróbuje utworzyć Employeeobiekt, zobaczy, że Employeema on zależność od Address, więc najpierw utworzy Addressobiekt (obiekt zależny), a następnie wstrzyknie go do Employeeobiektu.

  • Inversion of Control ( IoC ) i Dependency Injection ( DI ) są używane zamiennie. IoC jest osiągane przez DI. DI to proces zapewniania zależności, a IoC jest końcowym wynikiem DI. ( Uwaga: DI nie jest jedynym sposobem na osiągnięcie IoC. Istnieją również inne sposoby .)

  • Dzięki DI odpowiedzialność za tworzenie obiektów jest przenoszona z naszego kodu aplikacji do kontenera Spring; zjawisko to nazywa się IoC.

  • Wstrzyknięcie zależności można wykonać za pomocą iniekcji ustawiającej lub iniekcyjnej konstruktora.
Krishnakant Kadam
źródło
Nie zgadzam się. nie sądzę, żeby to było jasne wyjaśnienie. Dlaczego nie możesz po prostu utworzyć instancji „Adres” w polu „Pracownik” zamiast uzyskać strukturę do utworzenia i wstrzyknięcia? Potrzebny jest nieco bardziej szczegółowy przykład.
Boris,
2
@Boris Nikt nie powiedział, że nie można tworzyć instancji własnych obiektów. Ale jedynym celem odpowiedzi było pokazanie, jak możesz osiągnąć to samo dzięki DI. Możesz mieć zarówno DI, jak i obiekty tworzone przez kod klienta. To wciąż byłoby nazywane IOC, przynajmniej częściowo.
bogdan.rusu
Boris. Bardzo zazdrosny? To najlepsza odpowiedź w historii.
Aniket Kapse
31

Zapiszę moje proste rozumienie tych dwóch terminów: (Aby szybko zrozumieć, przeczytaj przykłady)

  • Wstrzykiwanie zależności (DI):
    Wstrzykiwanie zależności zwykle oznacza przekazanie obiektu zależnego jako parametru do metody, zamiast tworzenia przez metodę obiektu zależnego .
    W praktyce oznacza to, że metoda nie ma bezpośredniej zależności od konkretnej implementacji; jako parametr można przekazać każdą implementację, która spełnia wymagania.

    Dzięki tej implementacji obiektów definiuje się ich zależności. I wiosna to udostępnia.
    Prowadzi to do luźno powiązanego tworzenia aplikacji.

    Szybki przykład: TWORZONY OBIEKT PRACOWNIKA AUTOMATYCZNIE TWORZY OBIEKT ADRESOWY (jeśli adres jest zdefiniowany jako zależność przez obiekt Pracownik) *.

  • Kontener inwersji kontroli (IoC):
    Jest to typowa cecha frameworków, IoC zarządza obiektami Java
    - od tworzenia instancji do zniszczenia poprzez BeanFactory.
    - Komponenty Java, których instancje są tworzone przez kontener IoC, nazywane są ziarnami, a kontener IoC zarządza zakresem komponentu bean, zdarzeniami cyklu życia i wszystkimi funkcjami AOP, dla których został skonfigurowany i zakodowany.

    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.

    Wdrażając odwrócenie kontroli, konsument oprogramowania / obiektu otrzymuje więcej kontroli / opcji nad oprogramowaniem / obiektami, zamiast być kontrolowanym lub mieć mniej opcji.

    Odwrócenie kontroli jako wytyczna projektowa służy następującym celom:
    - Istnieje oddzielenie wykonania określonego zadania od realizacji.
    - Każdy moduł może skupić się na tym, do czego jest przeznaczony.
    - Moduły nie przyjmują żadnych założeń na temat tego, co robią inne systemy, ale opierają się na swoich umowach.
    - Wymiana modułów nie ma wpływu na inne moduły

Zachowam tutaj abstrakcję, możesz odwiedzić poniższe linki, aby uzyskać szczegółowe zrozumienie tematu.

Dobra lektura z przykładem

Szczegółowe wyjaśnienie

VdeX
źródło
11

W Spring Objects są luźno powiązane, tzn. Każda klasa jest od siebie niezależna, więc wszystko można przetestować indywidualnie. Jednak w przypadku korzystania z tych klas klasa może być zależna od innych klas, które należy najpierw utworzyć.

Tak więc mówimy spring, że klasa A jest zależna od klasy B. Tak więc, podczas tworzenia komponentu bean (podobnie jak klasa) dla klasy A, tworzy ona instancję klasy B przed klasą A i wstrzykuje ją do klasy A za pomocą metod ustawiania lub konstruktora DI. To znaczy, mówimy wiosnie o zależności w czasie wykonywania. To jest DI.

Ponieważ powierzamy Springowi odpowiedzialność za tworzenie obiektów (fasolek), utrzymywanie ich i ich agregacji na Spring, zamiast na sztywno je kodować, nazywamy to Inversion Of Control (IOC).

Venkateswara Rao
źródło
7

Odwrócenie kontroli (IOC):

IoC to wzorzec projektowy, który opisuje odwrócenie przepływu sterowania w systemie, więc przepływ wykonania nie jest kontrolowany przez centralny fragment kodu. Oznacza to, że komponenty powinny zależeć tylko od abstrakcji innych komponentów i nie są odpowiedzialne za obsługę tworzenia zależnych obiektów. Zamiast tego wystąpienia obiektów są dostarczane w czasie wykonywania przez kontener IoC za pośrednictwem iniekcji zależności (DI).

IoC umożliwia lepsze projektowanie oprogramowania, które ułatwia ponowne wykorzystanie, luźne łączenie i łatwe testowanie komponentów oprogramowania.

Wstrzykiwanie zależności (DI):

DI to technika przekazywania zależności do konstruktora obiektu. Jeśli obiekt został załadowany z kontenera, to jego zależności zostaną automatycznie dostarczone przez kontener. Pozwala to na wykorzystanie zależności bez konieczności ręcznego tworzenia instancji. Zmniejsza to sprzężenie i zapewnia większą kontrolę nad czasem życia instancji obiektów.

kliknij, aby zobaczyć więcej

Greesh Kumar
źródło
6

Spring: Spring to kontener „Inversion of Control” dla platformy Java.

Inversion of Control (IoC): Inversion of Control (IoC) to zorientowana obiektowo praktyka programowania, w której sprzężenie obiektów jest ograniczone w czasie wykonywania przez obiekt „asemblera” i zazwyczaj nie można ich rozpoznać w czasie kompilacji przy użyciu analizy statycznej.

Dependency Injection (DI): „Wstrzykiwanie zależności to wzorzec projektowy oprogramowania, który umożliwia usuwanie zakodowanych na stałe zależności i umożliwia ich zmianę, czy to w czasie wykonywania, czy w czasie kompilacji”. -wiki.

Nadhu
źródło
Jak to jest prostsze niż to, co już istnieje (skąd bierze się ta odpowiedź)? Nie uwzględnia prośby PO o prostotę, chyba że podwójne cudzysłowy wokół terminologii w magiczny sposób ułatwiają sprawę.
Płomień udun
6

Odwrócenie kontroli - oznacza przekazanie kontroli nad tworzeniem i tworzeniem ziaren wiosennych w kontenerze Spring IOC, a jedyną pracą wykonywaną przez programistę jest konfigurowanie ziaren w pliku spring xml.

Wstrzykiwanie zależności

Rozważmy klasowego pracownika

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

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


}

i rozważ adres klasy

class Address {
   private String street;
   private String city;

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

  }
}

W powyższym kodzie wartości klasy adresu zostaną ustawione tylko wtedy, gdy zostanie utworzona instancja klasy Employee, co jest zależnością klasy Address od klasy Employee. Spring rozwiązuje ten problem za pomocą koncepcji Dependency Injection, zapewniając dwa sposoby wstrzyknięcia tej zależności.

  1. Wstrzyknięcie setera

Setter w klasie Employee, która przyjmuje odwołanie do klasy Address

public void setAddress(Address addr) {
    this.address = addr;
}
  1. Wstrzyknięcie konstruktora

Konstruktor w klasie Employee, która akceptuje adres

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

W ten sposób wartości klasy Address można ustawić niezależnie za pomocą iniekcji ustawiającej / konstruktora.

Hetal Rachh
źródło
3

Odwrócenie kontroli to ogólna zasada projektowania architektury oprogramowania, która pomaga w tworzeniu łatwych w utrzymaniu modułowych struktur oprogramowania wielokrotnego użytku.

Jest to zasada projektowa, w której Flow of Control jest „odbierany” z ogólnej biblioteki lub kodu wielokrotnego użytku.

Aby lepiej to zrozumieć, zobaczmy, jak kodowaliśmy we wczesnych dniach kodowania. W językach proceduralnych / tradycyjnych logika biznesowa generalnie steruje przepływem aplikacji i „wywołuje” ogólny lub wielokrotnego użytku kod / funkcje. Na przykład w prostej aplikacji konsoli mój przepływ kontroli jest kontrolowany przez instrukcje mojego programu, które mogą obejmować wywołania niektórych ogólnych funkcji wielokrotnego użytku.

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

W przeciwieństwie do IoC, struktury są kodem wielokrotnego użytku, który „wywołuje” logikę biznesową.

Na przykład w systemie opartym na systemie Windows platforma będzie już dostępna do tworzenia elementów interfejsu użytkownika, takich jak przyciski, menu, okna i okna dialogowe. Kiedy piszę logikę biznesową mojej aplikacji, byłyby to zdarzenia frameworka, które wywołałyby mój kod logiki biznesowej (gdy zdarzenie jest wyzwalane), a NIE odwrotnie.

Chociaż kod frameworka nie jest świadomy mojej logiki biznesowej, nadal będzie wiedział, jak wywołać mój kod. Osiąga się to za pomocą zdarzeń / delegatów, wywołań zwrotnych itp. Tutaj Sterowanie przepływem jest „odwrócone”.

Tak więc zamiast uzależniać przepływ sterowania od statycznie powiązanych obiektów, przepływ zależy od ogólnego wykresu obiektu i relacji między różnymi obiektami.

Dependency Injection to wzorzec projektowy, który implementuje zasadę IoC do rozwiązywania zależności obiektów.

Mówiąc prościej, kiedy próbujesz pisać kod, będziesz tworzyć i używać różnych klas. Jedna klasa (klasa A) może używać innych klas (klasa B i / lub D). Tak więc klasy B i D są zależnościami klasy A.

Prostą analogią będzie samochód klasy. Samochód może zależeć od innych klas, takich jak silnik, opony i nie tylko.

Dependency Injection sugeruje, że zamiast klas zależnych (tutaj Class Car) tworzących swoje zależności (Class Engine i class Tire), klasa powinna zostać wstrzyknięta konkretną instancją zależności.

Przyjrzyjmy się bardziej praktycznemu przykładowi. Weź pod uwagę, że piszesz własny TextEditor. Między innymi możesz mieć moduł sprawdzania pisowni, który zapewnia użytkownikowi możliwość sprawdzenia literówek w jego tekście. Prostą implementacją takiego kodu może być:

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;

    }

}

Na pierwszy rzut oka wszystko wygląda różowo. Użytkownik napisze jakiś tekst. Deweloper przechwyci tekst i wywoła funkcję CheckSpellings oraz znajdzie listę literówek, które pokaże użytkownikowi.

Wydaje się, że wszystko działa świetnie, aż pewnego pięknego dnia jeden użytkownik zacznie pisać po francusku w edytorze.

Aby zapewnić obsługę większej liczby języków, potrzebujemy więcej sprawdzania pisowni. Prawdopodobnie francuski, niemiecki, hiszpański itp.

Tutaj stworzyliśmy ściśle powiązany kod z "angielskim" SpellChecker, który jest ściśle powiązany z naszą klasą TextEditor, co oznacza, że ​​nasza klasa TextEditor jest zależna od EnglishSpellChecker lub innymi słowy, EnglishSpellCheker jest zależnością dla TextEditor. Musimy usunąć tę zależność. Ponadto nasz edytor tekstu potrzebuje sposobu na przechowywanie konkretnych odniesień do dowolnego modułu sprawdzania pisowni w oparciu o uznanie programisty w czasie wykonywania.

Tak więc, jak widzieliśmy we wprowadzeniu DI, sugeruje, że klasa powinna zostać wstrzyknięta wraz z jej zależnościami. Zatem to kod wywołujący powinien być odpowiedzialny za wstrzyknięcie wszystkich zależności do wywoływanej klasy / kodu. Więc możemy zmienić strukturę naszego kodu jako

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.

    }

}

W naszym przykładzie klasa TextEditor powinna otrzymać konkretną instancję typu ISpellChecker.

Teraz zależność można wstrzyknąć w konstruktorze, właściwości publicznej lub metodzie.

Spróbujmy zmienić naszą klasę za pomocą Constructor DI. Zmieniona klasa TextEditor będzie wyglądać mniej więcej tak:

Class TextEditor

{

    ISpellChecker objSpellChecker;

    string Text;



    public void TextEditor(ISpellChecker objSC)

    {

        objSpellChecker = objSC;

    }



    public ArrayList <typos> CheckSpellings()

    {

        return objSpellChecker.CheckSpelling();

    }

}

Aby wywołujący kod podczas tworzenia edytora tekstu mógł wstrzyknąć odpowiedni typ sprawdzania pisowni do instancji TextEditor.

Możesz przeczytać cały artykuł tutaj

Amrit
źródło
1

Tradycyjnym sposobem na uzyskanie instancji adresu w Employee byłoby utworzenie nowej instancji klasy Address. Spring tworzy wszystkie zależne od nas obiekty, dlatego nie musimy się martwić o obiekt.

Tak więc wiosną polegamy tylko na pojemniku sprężyny, który dostarcza nam obiekt zależności.

SumataPatil
źródło
1

MKOl to technika, w której pozwalasz komuś innemu stworzyć obiekt za Ciebie. A kimś innym w przypadku wiosny jest kontener IOC.

Dependency Injection to technika, w której jeden obiekt dostarcza zależności innego obiektu.

demon
źródło