Zostało już opublikowanych kilka pytań z konkretnymi pytaniami dotyczącymi wstrzykiwania zależności , na przykład kiedy z niego korzystać i jakie są dostępne ramy. Jednak,
Co to jest zastrzyk zależności i kiedy / dlaczego należy go stosować lub nie?
Odpowiedzi:
Dependency Injection przekazuje zależność do innych obiektów lub frameworka (aplikator zależności).
Wstrzykiwanie zależności ułatwia testowanie. Wstrzyknięcie można wykonać za pomocą konstruktora .
SomeClass()
ma następujący konstruktor:Problem : W przypadku
myObject
złożonych zadań, takich jak dostęp do dysku lub dostęp do sieci, trudno jest przeprowadzić test jednostkowySomeClass()
. Programiści muszą kpićmyObject
i mogą przechwycić połączenie fabryczne.Alternatywne rozwiązanie :
myObject
jako argument do konstruktoramyObject
można przekazać bezpośrednio, co ułatwia testowanie.Trudniej jest izolować komponenty w testach jednostkowych bez wstrzykiwania zależności.
Kiedy w 2013 roku napisałem tę odpowiedź, był to główny temat na blogu testowym Google . Pozostaje to dla mnie największą zaletą, ponieważ programiści nie zawsze potrzebują dodatkowej elastyczności przy projektowaniu w czasie wykonywania (na przykład dla lokalizatora usług lub podobnych wzorców). Programiści często muszą izolować klasy podczas testowania.
źródło
Najlepsza definicja, jaką do tej pory znalazłem, to James Shore :
Jest też artykuł Martina Fowlera, który może okazać się przydatny.
Wstrzykiwanie zależności polega w zasadzie na dostarczeniu obiektów, których potrzebuje obiekt (jego zależności), zamiast samemu je konstruować. Jest to bardzo przydatna technika testowania, ponieważ pozwala na kpienie lub eliminowanie zależności.
Zależności można wstrzykiwać do obiektów na wiele sposobów (takich jak wstrzykiwanie konstruktora lub wstrzykiwanie setera). W tym celu można nawet użyć specjalistycznych struktur wstrzykiwania zależności (np. Spring), ale z pewnością nie są one wymagane. Te frameworki nie są potrzebne do wstrzyknięcia zależności. Bezpośrednie tworzenie instancji i przekazywanie obiektów (zależności) jest tak samo dobre jak wstrzyknięcie jak wstrzyknięcie przez framework.
źródło
Znalazłem ten zabawny przykład w kategoriach luźnego sprzężenia :
Każda aplikacja składa się z wielu obiektów, które współpracują ze sobą w celu wykonania użytecznych czynności. Tradycyjnie każdy obiekt jest odpowiedzialny za uzyskanie własnych odniesień do obiektów zależnych (zależności), z którymi współpracuje. Prowadzi to do wysoce sprzężonych klas i trudnego do przetestowania kodu.
Na przykład rozważmy
Car
przedmiot.A
Car
zależy od kół, silnika, paliwa, akumulatora itp. Tradycyjnie definiujemy markę takich zależnych obiektów wraz z definicjąCar
obiektu.Bez wtrysku zależności (DI):
Tutaj
Car
obiekt jest odpowiedzialny za tworzenie obiektów zależnych.Co jeśli chcemy zmienić typ obiektu zależnego - powiedzmy
Wheel
- po początkowychNepaliRubberWheel()
nakłuciach? Musimy odtworzyć obiekt Car z jego nową zależnościąChineseRubberWheel()
, ale tylkoCar
producent może to zrobić.Co zatem
Dependency Injection
dla nas robi ...?Podczas stosowania wstrzykiwania zależności obiekty otrzymują swoje zależności w czasie wykonywania, a nie w czasie kompilacji (czas produkcji samochodu) . Abyśmy mogli teraz zmieniać,
Wheel
kiedy tylko chcemy. Tutaj można wstrzyknąćdependency
(wheel
)Car
w czasie wykonywania.Po zastosowaniu wstrzyknięcia zależności:
Tutaj jesteśmy wstrzykiwanie z zależnościami (koło i akumulator) przy starcie. Stąd termin: wstrzyknięcie zależności.
Źródło: Zrozumienie wstrzykiwania zależności
źródło
new
do opona? Ja nie. Wszystko, co muszę zrobić, to kupić od nich (wstrzyknąć przez param), zainstalować i wah-lah! Tak więc, wracając do programowania, powiedzmy, że projekt C # musi korzystać z istniejącej biblioteki / klasy, istnieją dwa sposoby uruchomienia / debugowania, 1-dodawanie odwołania do całego projektunew
niego, opcja 2 przekazuje ją jako parametr. Może nie być dokładne, ale proste, głupie, łatwe do zrozumienia.Wstrzykiwanie zależności to praktyka polegająca na tym, że obiekty są projektowane w taki sposób, że otrzymują instancje obiektów z innych fragmentów kodu zamiast konstruować je wewnętrznie. Oznacza to, że każdy obiekt implementujący interfejs, który jest wymagany przez obiekt, można podstawić bez zmiany kodu, co upraszcza testowanie i poprawia odsprzęganie.
Rozważmy na przykład następujące klauzule:
W tym przykładzie wdrożenie
PersonService::addManager
iPersonService::removeManager
potrzebowałoby wystąpienia instancjiGroupMembershipService
w celu wykonania swojej pracy. Bez wstrzykiwania zależności tradycyjnym sposobem wykonania tego byłoby utworzenie nowego elementuGroupMembershipService
w konstruktorzePersonService
i użycie tego atrybutu instancji w obu funkcjach. Jednakże, jeśli konstruktorGroupMembershipService
ma wiele rzeczy, których wymaga, lub jeszcze gorzej, istnieją pewne „ustawiacze” inicjujące, które należy wywołać wGroupMembershipService
, kod rośnie dość szybko, aPersonService
teraz zależy nie tylko od,GroupMembershipService
ale i wszystkiego innego, coGroupMembershipService
zależy od. Co więcej, powiązanie zGroupMembershipService
jest zakodowane na stałe,PersonService
co oznacza, że nie można „zrobić manekina”GroupMembershipService
do celów testowych lub do wykorzystania wzorca strategii w różnych częściach aplikacji.Dzięki Dependency Injection zamiast tworzenia instancji
GroupMembershipService
wewnątrzPersonService
, możesz przekazać jąPersonService
konstruktorowi lub dodać właściwość (moduł pobierający i ustawiający), aby ustawić jego lokalną instancję. Oznacza to, żePersonService
nie musisz się już martwić, jak utworzyćGroupMembershipService
, akceptuje tylko te, które otrzymałeś i współpracuje z nimi. Oznacza to również, że wszystko, co jest podklasąGroupMembershipService
lub implementacjąGroupMembershipService
interfejsu, może zostać „wstrzyknięte” doPersonService
iPersonService
nie musi wiedzieć o zmianie.źródło
Przyjęta odpowiedź jest dobra - ale chciałbym dodać do tego, że DI jest bardzo podobny do klasycznego unikania stałych zakodowanych w kodzie.
Kiedy używasz stałej, np. Nazwy bazy danych, szybko przenosisz ją z wnętrza kodu do jakiegoś pliku konfiguracyjnego i przekazujesz zmienną zawierającą tę wartość do miejsca, w którym jest potrzebna. Powodem tego jest to, że te stałe zwykle zmieniają się częściej niż reszta kodu. Na przykład, jeśli chcesz przetestować kod w testowej bazie danych.
DI jest analogiczne do tego w świecie programowania obiektowego. Wartości zamiast stałych literałów są całymi obiektami - ale powód przeniesienia tworzącego je kodu z kodu klasy jest podobny - obiekty zmieniają się częściej niż kod, który ich używa. Jednym z ważnych przypadków, w których taka zmiana jest potrzebna, są testy.
źródło
Spróbujmy prostego przykładu z klasami samochodów i silników , każdy samochód potrzebuje silnika, aby pojechać gdziekolwiek, przynajmniej na razie. Poniżej poniżej, jak będzie wyglądał kod bez wstrzykiwania zależności.
Aby utworzyć instancję klasy Car, użyjemy następnego kodu:
Problem z tym kodem, który ściśle powiązaliśmy z GasEngine i jeśli zdecydujemy się go zmienić na ElectricityEngine, będziemy musieli przepisać klasę samochodu. Im większa aplikacja, tym więcej problemów i bólu głowy będziemy musieli dodać i użyć nowego typu silnika.
Innymi słowy, przy takim podejściu nasza klasa wysokiego poziomu zależy od klasy GasEngine niższego poziomu, która narusza zasadę inwersji zależności (DIP) od SOLID. DIP sugeruje, że powinniśmy polegać na abstrakcjach, a nie na konkretnych klasach. Aby to spełnić, wprowadzamy interfejs IEngine i przepisujemy kod jak poniżej:
Teraz nasza klasa samochodów jest zależna tylko od interfejsu IEngine, a nie od konkretnej implementacji silnika. Teraz jedyną sztuczką jest to, jak stworzyć instancję samochodu i nadać jej konkretną konkretną klasę silnika, taką jak GasEngine lub ElectricityEngine. Tam właśnie wchodzi Dependency Injection .
Tutaj w zasadzie wstrzykujemy (przekazujemy) naszą zależność (instancję silnika) do konstruktora Car. Więc teraz nasze klasy mają luźne sprzężenie między obiektami i ich zależnościami i możemy łatwo dodawać nowe typy silników bez zmiany klasy samochodu.
Główną zaletą wstrzykiwania zależności jest to, że klasy są luźniej sprzężone, ponieważ nie mają sztywnych zależności. Jest to zgodne z zasadą inwersji zależności, o której wspomniano powyżej. Zamiast odwoływać się do konkretnych implementacji, klasy żądają abstrakcji (zwykle interfejsów ), które są im dostarczane, kiedy klasa jest konstruowana.
Również gdy mamy wiele zależności, bardzo dobrą praktyką jest używanie kontenerów Inversion of Control (IoC), dzięki którym możemy stwierdzić, które interfejsy powinny być mapowane na konkretne implementacje dla wszystkich naszych zależności, i możemy sprawić, aby te zależności zostały dla nas rozwiązane podczas konstruowania nasz przedmiot. Na przykład możemy określić w mapowaniu kontenera IoC, że zależność IEngine powinna być mapowana na klasę GasEngine, a kiedy poprosimy kontener IoC o instancję naszej klasy Car , automatycznie skonstruuje naszą klasę Car z zależnością GasEngine przeszedł.
AKTUALIZACJA: Niedawno obejrzałem kurs na temat EF Core autorstwa Julie Lerman, a także polubiłem jej krótką definicję dotyczącą DI.
źródło
Wyobraźmy sobie, że chcesz łowić ryby:
Bez zastrzyku uzależnienia musisz sam wszystko załatwić. Musisz znaleźć łódź, kupić wędkę, poszukać przynęty itp. Oczywiście jest to możliwe, ale wiąże się to z dużą odpowiedzialnością. Pod względem oprogramowania oznacza to, że musisz wykonać wyszukiwanie wszystkich tych rzeczy.
Dzięki wstrzyknięciu zależności ktoś zajmuje się całym przygotowaniem i udostępnia wymagane wyposażenie. Otrzymasz („zastrzyk”) łódź, wędkę i przynętę - wszystko gotowe do użycia.
źródło
To jest najprostsze wyjaśnienie dotyczące wstrzykiwania zależności i kontenera wstrzykiwania zależności , jakie kiedykolwiek widziałem:
Bez wstrzykiwania zależności
Z wtryskiem zależnym
Korzystanie z pojemnika do wstrzykiwań zależności
Wstrzykiwanie zależności i zależność Pojemniki do wstrzykiwań są różne:
Nie potrzebujesz pojemnika do wstrzykiwania zależności. Jednak pojemnik może ci pomóc.
źródło
Czy „wstrzykiwanie zależności” nie oznacza po prostu używania sparametryzowanych konstruktorów i ustawiaczy publicznych?
Artykuł Jamesa Shore'a pokazuje następujące przykłady do porównania .
źródło
new DatabaseThingie()
nie wygeneruje prawidłowej instancji myDatabase.Aby uczynić koncepcję wtrysku zależnego prostą do zrozumienia. Weźmy przykład przycisku przełącznika do przełączania (włączania / wyłączania) żarówki.
Bez wstrzykiwania zależności
Switch musi wcześniej wiedzieć, do której żarówki jestem podłączony (zależność na stałe). Więc,
Przełącznik -> Przełącznik PermanentBulb // jest bezpośrednio podłączony do stałej żarówki, testowanie nie jest łatwe
Z wtryskiem zależnym
Switch wie tylko, że muszę włączyć / wyłączyć cokolwiek, co zostanie mi przekazane. Więc,
Przełącznik -> Żarówka 1 LUB Żarówka 2 LUB NightBulb (zależność wstrzyknięta)
Modyfikacja Jamesa dla przełącznika i żarówki:
źródło
Co to jest wstrzykiwanie zależności (DI)?
Jak powiedzieli inni, Dependency Injection (DI) usuwa odpowiedzialność za bezpośrednie tworzenie i zarządzanie długością życia, innych obiektów obiektowych, od których zależy nasza klasa zainteresowań (klasa konsumentów) (w sensie UML ). Te instancje są zamiast tego przekazywane do naszej klasy konsumenta, zwykle jako parametry konstruktora lub za pomocą ustawiaczy właściwości (zarządzanie instancją obiektu zależności i przekazywaniem do klasy konsumenta jest zwykle wykonywane przez kontener Inversion of Control (IoC) , ale to inny temat) .
DI, DIP i SOLID
W szczególności, w paradygmacie Roberta C Martina SOLID zasad Object Oriented projekt ,
DI
jest jednym z możliwych implementacji Dependency Inversion Principle (DIP) . DIP jestD
zSOLID
mantrą - inne implementacje DIP obejmują lokalizatora usług i wzorców wtyczki.Celem DIP jest oddzielenie szczelne, betonowe zależności między klasami, a zamiast tego, aby poluzować sprzęgło za pomocą abstrakcji, co można osiągnąć poprzez
interface
,abstract class
lubpure virtual class
, w zależności od języka i podejścia stosowanego.Bez DIP nasz kod (nazwałam tę „klasą konsumpcyjną”) jest bezpośrednio połączony z konkretną zależnością, a także często jest obciążony odpowiedzialnością za uzyskanie i zarządzanie instancją tej zależności, tj. Koncepcyjnie:
Podczas gdy po zastosowaniu DIP wymóg został rozluźniony, a problem uzyskiwania i zarządzania
Foo
czasem trwania zależności został usunięty:Dlaczego warto korzystać z DIP (i DI)?
Oddzielenie zależności między klasami w ten sposób pozwala na łatwe zastąpienie tych klas zależności innymi implementacjami, które również spełniają warunki abstrakcji (np. Zależność można przełączać za pomocą innej implementacji tego samego interfejsu). Ponadto, jak wspominają inni, ewentualnie Najczęstszym powodem do klas oddzielić poprzez DIP jest umożliwienie spożywania klasy należy badać w izolacji, ponieważ te same zależności mogą być teraz zgaszone i / lub wyśmiewany.
Jedną z konsekwencji DI jest to, że zarządzanie żywotnością instancji obiektów zależności nie jest już kontrolowane przez konsumującą klasę, ponieważ obiekt zależności jest teraz przekazywany do konsumującej klasy (poprzez wstrzyknięcie konstruktora lub ustawiacza).
Można to zobaczyć na różne sposoby:
Create
w fabryce w razie potrzeby i zlikwidować je po zakończeniu.Kiedy stosować DI?
MyDepClass
czy wątek jest bezpieczny - co, jeśli zrobimy z niego singleton i wstrzykniemy ten sam przypadek wszystkim konsumentom?)Przykład
Oto prosta implementacja w języku C #. Biorąc pod uwagę poniższą klasę konsumpcyjną:
Choć z pozoru nieszkodliwy, ma dwie
static
zależności od dwóch innych klasSystem.DateTime
iSystem.Console
, co nie tylko ogranicza opcje wyjściowe rejestrowania (logowanie do konsoli będzie bezwartościowe, jeśli nikt nie patrzy), ale co gorsza, trudno jest automatycznie przetestować, biorąc pod uwagę zależność od niedeterministyczny zegar systemowy.Możemy jednak zastosować się
DIP
do tej klasy, wyodrębniając obawę związaną z oznaczaniem czasu jako zależnością i łączącMyLogger
tylko z prostym interfejsem:Możemy również rozluźnić zależność od
Console
abstrakcji, takiej jak aTextWriter
. Wstrzykiwanie zależności jest zwykle realizowane albo jakoconstructor
wstrzyknięcie (przekazanie abstrakcji do zależności jako parametru do konstruktora klasy konsumującej) lubSetter Injection
(przekazanie zależności przezsetXyz()
ustawiacz lub właściwość .Net ze{set;}
zdefiniowaną). Preferowany jest Constructor Injection, ponieważ gwarantuje to, że klasa będzie w poprawnym stanie po zbudowaniu i pozwoli na oznaczenie wewnętrznych pól zależności jakoreadonly
(C #) lubfinal
(Java). Tak więc używając zastrzyku konstruktora w powyższym przykładzie, pozostawia nam to:(Należy
Clock
podać konkret, do którego można oczywiście wrócićDateTime.Now
, a dwie zależności muszą być zapewnione przez kontener IoC poprzez wstrzyknięcie konstruktora)Można zbudować automatyczny test jednostkowy, który ostatecznie dowodzi, że nasz rejestrator działa poprawnie, ponieważ teraz mamy kontrolę nad zależnościami - czasem i możemy szpiegować zapisywane dane wyjściowe:
Następne kroki
Wstrzykiwanie zależności jest niezmiennie związane z kontenerem Inwersji Kontroli (IoC) , aby wstrzykiwać (udostępniać) konkretne wystąpienia zależności i zarządzać instancjami długości życia. Podczas procesu konfiguracji / ładowania początkowego
IoC
kontenery umożliwiają zdefiniowanie następujących elementów:IBar
, zwracaConcreteBar
instancję” )IDisposable
i przyjmują odpowiedzialność zaDisposing
zależności zgodnie ze skonfigurowanym zarządzaniem żywotnością.Zazwyczaj po skonfigurowaniu / załadowaniu kontenerów IoC działają one płynnie w tle, umożliwiając koderowi skupienie się na dostępnym kodzie zamiast martwienia się o zależności.
Jak w powyższym przykładzie, odsprzężenie zależności wymaga pewnego wysiłku projektowego, a dla dewelopera konieczna jest zmiana paradygmatu, aby przełamać nawyk
new
bezpośredniego uzgadniania zależności i zamiast tego ufać kontenerowi w zarządzaniu zależnościami.Ale korzyści jest wiele, zwłaszcza możliwość dokładnego przetestowania klasy zainteresowań.
Uwaga : Tworzenie / mapowanie / projekcja (via
new ..()
) POCO / POJO / Serialization DTOs / Entity Graphs / Anonymous JSON prognoz i in. - tj. Klasy lub rekordy „Tylko dane” - używane lub zwracane z metod nie są uważane za Zależności (w UML sense) i nie podlega DI. Używanienew
do wyświetlania jest w porządku.źródło
Cały sens Dependency Injection (DI) polega na utrzymaniu kodu źródłowego aplikacji w czystości i stabilności :
Praktycznie każdy wzorzec projektu oddziela obawy, aby przyszłe zmiany wpływały na minimalne pliki.
Specyficzną domeną DI jest delegowanie konfiguracji zależności i inicjalizacja.
Przykład: DI ze skryptem powłoki
Jeśli od czasu do czasu pracujesz poza Javą, przypomnij sobie, jak
source
często jest używana w wielu językach skryptowych (Shell, Tcl itp., A nawetimport
w Pythonie niewłaściwie wykorzystywanych do tego celu).Rozważ prosty
dependent.sh
skrypt:Skrypt jest zależny: nie zadziała samodzielnie (
archive_files
nie jest zdefiniowany).Zdefiniować
archive_files
warchive_files_zip.sh
skrypcie realizacji (używajączip
w tym przypadku):Zamiast
source
-ing skryptu implementacyjnego bezpośrednio w skrypcie zależnym, używaszinjector.sh
„kontenera”, który otacza oba „komponenty”:archive_files
Zależność właśnie został wstrzyknięty do zależnego skryptu.Mogłeś wstrzyknąć zależność, która implementuje
archive_files
za pomocątar
lubxz
.Przykład: usunięcie DI
Gdyby
dependent.sh
skrypt używał zależności bezpośrednio, podejście nazwano by wyszukiwaniem zależności (co jest odwrotne do wstrzykiwania zależności ):Problem polega na tym, że zależny „komponent” musi sam dokonać inicjalizacji.
Kod źródłowy „komponentu” nie jest ani czysty, ani stabilny, ponieważ każda zmiana w inicjalizacji zależności wymaga również nowej wersji pliku kodu źródłowego „komponentów”.
Ostatnie słowa
DI nie jest tak mocno podkreślany i popularyzowany jak w frameworkach Java.
Ale jest to ogólne podejście do podzielenia obaw:
Używanie konfiguracji tylko z wyszukiwaniem zależności nie pomaga, ponieważ liczba parametrów konfiguracyjnych może się zmieniać w zależności od zależności (np. Nowy typ uwierzytelnienia), a także liczba obsługiwanych typów zależności (np. Nowy typ bazy danych).
źródło
Wszystkie powyższe odpowiedzi są dobre, moim celem jest wyjaśnienie pojęcia w prosty sposób, aby każdy bez znajomości programowania mógł zrozumieć pojęcie
Wstrzykiwanie zależności jest jednym z wzorców projektowych, które pomagają nam tworzyć złożone systemy w prostszy sposób.
Widzimy szeroką gamę zastosowań tego wzoru w naszym codziennym życiu. Niektóre z przykładów to magnetofon, VCD, napęd CD itp.
Powyższe zdjęcie jest obrazem przenośnego magnetofonu szpulowego z połowy XX wieku. Źródło .
Podstawowym celem magnetofonu jest nagrywanie lub odtwarzanie dźwięku.
Podczas projektowania systemu wymaga szpuli do nagrywania lub odtwarzania dźwięku lub muzyki. Istnieją dwie możliwości zaprojektowania tego systemu
Jeśli użyjemy pierwszego, musimy otworzyć maszynę, aby zmienić rolkę. jeśli zdecydujemy się na drugi, czyli zakładanie haka na rolkę, uzyskujemy dodatkową korzyść z grania dowolnej muzyki poprzez zmianę rolki. a także redukując funkcję tylko do grania na rolce.
Podobnie jak mądry wstrzykiwanie zależności jest procesem uzewnętrzniania zależności, aby skupić się tylko na konkretnej funkcjonalności komponentu, tak aby niezależne komponenty mogły być ze sobą łączone w celu utworzenia złożonego systemu.
Główne korzyści, które osiągnęliśmy dzięki zastosowaniu wstrzykiwania zależności.
Teraz dni ta koncepcja stanowi podstawę dobrze znanych ram w świecie programowania. Spring Angular itp. To dobrze znane frameworki programowe zbudowane na szczycie tej koncepcji
Wstrzykiwanie zależności to wzorzec używany do tworzenia instancji obiektów, na których polegają inne obiekty bez wiedzy w czasie kompilacji, która klasa zostanie użyta do zapewnienia tej funkcjonalności lub po prostu sposób wstrzykiwania właściwości do obiektu nazywa się wstrzykiwaniem zależności.
Przykład wstrzyknięcia zależności
Wcześniej piszemy taki kod
W przypadku wstrzykiwania zależności wtryskiwacz zależności usunie dla nas instancję
Możesz także przeczytać
Różnica między inwersją kontroli i iniekcji zależności
źródło
Co to jest wstrzyknięcie zależności?
Wstrzykiwanie zależności (DI) oznacza rozdzielanie obiektów, które są od siebie zależne. Powiedzmy, że obiekt A jest zależny od obiektu B, więc pomysł polega na oddzieleniu tych obiektów od siebie. Nie musimy na stałe kodować obiektu przy użyciu nowego słowa kluczowego, zamiast współdzielić zależności między obiektami w czasie wykonywania, pomimo czasu kompilacji. Jeśli o tym porozmawiamy
Jak działa wstrzykiwanie zależności na wiosnę:
Nie musimy na stałe kodować obiektu za pomocą nowego słowa kluczowego, a raczej zdefiniować zależność fasoli w pliku konfiguracyjnym. Kontener sprężynowy będzie odpowiedzialny za podłączenie wszystkich.
Inwersja kontroli (MKOl)
MKOl jest ogólną koncepcją i można ją wyrazić na wiele różnych sposobów, a wstrzykiwanie zależności jest jednym konkretnym przykładem MKOl.
Dwa rodzaje wstrzykiwania zależności:
1. Zastrzyk zależny od konstruktora:
DI oparte na konstruktorze jest osiągane, gdy kontener wywołuje konstruktor klasy z wieloma argumentami, z których każdy reprezentuje zależność od innej klasy.
2. Wstrzykiwanie zależności na bazie settera:
DI oparte na seterach jest osiągane przez kontener wywołujący metody setter dla twoich ziaren po wywołaniu konstruktora bez argumentu lub statycznej metody bez argumentu w celu utworzenia instancji komponentu bean.
UWAGA: Dobrą zasadą jest stosowanie argumentów konstruktora dla obowiązkowych zależności, a ustawiaczy dla zależności opcjonalnych. Zauważ, że jeśli używamy adnotacji opartych na adnotacji @Required na seterach, można użyć ich do stworzenia seterów jako wymaganych zależności.
źródło
Najlepszą analogią, jaką mogę wymyślić, jest chirurg i jego asystent (asystenci) w sali operacyjnej, gdzie chirurg jest główną osobą i jego asystentem, który zapewnia różne elementy chirurgiczne, gdy tego potrzebuje, aby chirurg mógł skoncentrować się na jednym rzecz, którą robi najlepiej (operacja). Bez asystenta chirurg musi sam zdobyć komponenty za każdym razem, gdy tego potrzebuje.
Krótko mówiąc, DI jest techniką polegającą na usunięciu wspólnej dodatkowej odpowiedzialności (obciążenia) na komponentach za pobranie komponentów zależnych poprzez ich przekazanie.
DI przybliża cię do zasady pojedynczej odpowiedzialności (SR), takiej jak
surgeon who can concentrate on surgery
.Kiedy stosować DI: Polecam używanie DI w prawie wszystkich projektach produkcyjnych (małych / dużych), szczególnie w ciągle zmieniających się środowiskach biznesowych :)
Powód: Ponieważ chcesz, aby Twój kod był łatwy do przetestowania, naśladowania itp., Abyś mógł szybko przetestować zmiany i wypchnąć go na rynek. Poza tym dlaczego nie miałbyś, skoro masz wiele niesamowitych darmowych narzędzi / ram, które wspierają cię w podróży do bazy kodu, w której masz większą kontrolę.
źródło
Przykład, mamy 2 klasy
Client
iService
.Client
będzie użytyService
Bez wstrzykiwania zależności
Sposób 1)
Sposób 2)
Sposób 3)
1) 2) 3) Korzystanie
Zalety
Niedogodności
Client
klasy testowejService
konstruktor, musimy zmienić kod we wszystkichService
obiektach tworzenia obiektuUżyj wstrzykiwania zależności
Sposób 1) Wstrzyknięcie konstruktora
Za pomocą
Sposób 2) Wstrzyknięcie setera
Za pomocą
Sposób 3) Wstrzyknięcie interfejsu
Czek https://en.wikipedia.org/wiki/Dependency_injection
===
Teraz ten kod jest już śledzony
Dependency Injection
i jest łatwiej dlaClient
klasy testowej .Jednak nadal używamy
new Service()
wiele czasu i nie jest dobrze, gdyService
konstruktor zmiany jest zmienny. Aby temu zapobiec, możemy użyć wtryskiwacza DI, takiego jak1) Prosta instrukcja
Injector
Za pomocą
2) Użyj biblioteki: dla systemu Android sztylet2
Zalety
Service
należy go zmienić tylko w klasie InjectorConstructor Injection
, kiedy spojrzysz na konstruktorClient
, zobaczysz ile zależnościClient
klasNiedogodności
Constructor Injection
,Service
obiekt jest tworzony podczasClient
tworzenia, czasami używamy funkcji wClient
klasie bez użycia,Service
więc utworzonyService
zostaje zmarnowanyDefinicja wtrysku zależności
https://en.wikipedia.org/wiki/Dependency_injection
źródło
Oznacza to, że obiekty powinny mieć tyle zależności, ile jest potrzebne do wykonania ich zadania, a zależności powinny być nieliczne. Co więcej, zależności obiektu powinny dotyczyć interfejsów, a nie „konkretnych” obiektów, o ile to możliwe. (Konkretny obiekt to każdy obiekt utworzony za pomocą słowa kluczowego new.) Luźne sprzężenie zapewnia większą możliwość ponownego użycia, łatwiejszą konserwację i umożliwia łatwe dostarczanie „próbnych” obiektów zamiast kosztownych usług.
„Wstrzykiwanie zależności” (DI) jest również znane jako „Inwersja kontroli” (IoC), może być stosowane jako technika zachęcania do tego luźnego sprzężenia.
Istnieją dwa podstawowe podejścia do wdrażania DI:
Wtrysk konstruktora
Jest to technika przekazywania zależności między obiektami do konstruktora.
Zauważ, że konstruktor akceptuje interfejs, a nie konkretny obiekt. Należy również pamiętać, że wyjątek jest zgłaszany, jeśli parametr orderlayer ma wartość NULL. Podkreśla to znaczenie otrzymania prawidłowej zależności. Constructor Injection jest moim zdaniem preferowanym mechanizmem nadawania obiektowi swoich zależności. Podczas wywoływania obiektu jest jasne dla dewelopera, jakie zależności należy podać obiektowi „Osoba” w celu poprawnego wykonania.
Zastrzyk setera
Ale rozważ następujący przykład… Załóżmy, że masz klasę z dziesięcioma metodami, które nie mają zależności, ale dodajesz nową metodę, która ma zależność od IDAO. Możesz zmienić konstruktora, aby używał Constructor Injection, ale może to zmusić cię do zmiany wszystkich wywołań konstruktora w dowolnym miejscu. Alternatywnie, możesz po prostu dodać nowego konstruktora, który bierze zależność, ale wtedy skąd programista łatwo wie, kiedy użyć jednego konstruktora nad drugim. Wreszcie, jeśli tworzenie zależności jest bardzo kosztowne, dlaczego należy ją utworzyć i przekazać konstruktorowi, skoro może być używana rzadko? „Zastrzykiwanie setera” to kolejna technika DI, którą można zastosować w takich sytuacjach.
Zastrzyk Settera nie zmusza do przekazania zależności do konstruktora. Zamiast tego zależności są ustawiane na właściwości publiczne ujawniane przez obiekt w potrzebie. Jak sugerowano poprzednio, głównymi czynnikami motywującymi do tego są:
Oto przykład, jak wyglądałby powyższy kod:
źródło
Myślę, że skoro wszyscy pisali dla DI, zadam kilka pytań ...
Jest to oparte na opublikowanej odpowiedzi @Adam N.
Dlaczego PersonService nie musi się już martwić o GroupMembershipService? Wspomniałeś, że GroupMembership ma wiele rzeczy (obiektów / właściwości), od których zależy. Jeśli GMService był wymagany w PService, miałbyś go jako właściwość. Możesz wyśmiewać to, niezależnie od tego, czy wstrzyknąłeś go, czy nie. Jedynym momentem, w którym chciałbym, aby został wstrzyknięty, jest to, że GMService ma bardziej szczegółowe klasy potomne, których nie znasz do czasu uruchomienia. Następnie chcesz wstrzyknąć podklasę. Lub jeśli chcesz użyć tego jako singletonu lub prototypu. Szczerze mówiąc, plik konfiguracyjny ma wszystko zakodowane na stałe w zakresie podklasy dla typu (interfejsu), który zostanie wprowadzony podczas kompilacji.
EDYTOWAĆ
Miły komentarz Jose Maria Arranz na temat DI
DI zwiększa spójność poprzez usunięcie jakiejkolwiek potrzeby określenia kierunku zależności i napisania dowolnego kodu kleju.
Fałszywe. Kierunek zależności jest w formie XML lub jako adnotacje, a twoje zależności są zapisywane jako kod XML i adnotacje. XML i adnotacje SĄ kodem źródłowym.
DI zmniejsza sprzężenie, czyniąc wszystkie elementy modułowymi (tj. Wymiennymi) i ma dobrze zdefiniowane interfejsy.
Fałszywe. Nie potrzebujesz frameworka DI do zbudowania kodu modułowego opartego na interfejsach.
O wymiennych: dzięki bardzo prostemu archiwum .properties i Class.forName możesz zdefiniować, które klasy mogą być zmieniane. Jeśli JAKĄKOLWIEK klasę kodu można zmienić, Java nie jest dla Ciebie, użyj języka skryptowego. Nawiasem mówiąc: adnotacji nie można zmienić bez ponownej kompilacji.
Moim zdaniem istnieje jeden jedyny powód dla ram DI: redukcja płyty kotła. Dzięki dobrze wykonanemu systemowi fabrycznemu możesz zrobić to samo, bardziej kontrolowane i bardziej przewidywalne, jak preferowany framework DI, frameworki DI obiecują redukcję kodu (XML i adnotacje również są kodem źródłowym). Problem polega na tym, że redukcja płyty kotła jest po prostu realna w bardzo bardzo prostych przypadkach (jedna instancja na klasę i podobne), czasami w świecie rzeczywistym wybranie odpowiedniego obiektu usługi nie jest tak łatwe, jak odwzorowanie klasy na obiekt singletonu.
źródło
Popularne odpowiedzi są nieprzydatne, ponieważ definiują wstrzykiwanie zależności w sposób, który nie jest użyteczny. Zgódźmy się, że przez „zależność” rozumiemy jakiś wcześniejszy inny obiekt, którego potrzebuje nasz obiekt X. Ale nie mówimy, że robimy „zastrzyk zależności”, kiedy mówimy
Po prostu nazywamy to przekazywaniem parametrów do konstruktora. Robimy to regularnie od momentu wynalezienia konstruktorów.
„Wstrzykiwanie zależności” jest uważane za rodzaj „odwrócenia kontroli”, co oznacza, że część logiki jest usuwana z dzwoniącego. Nie dzieje się tak, gdy wywołujący przekazuje parametry, więc jeśli byłyby to DI, DI nie oznaczałoby odwrócenia kontroli.
DI oznacza, że istnieje poziom pośredni między dzwoniącym a konstruktorem, który zarządza zależnościami. Makefile to prosty przykład wstrzykiwania zależności. „Osoba dzwoniąca” to osoba wpisująca „make bar” w wierszu poleceń, a „konstruktor” to kompilator. Plik Makefile określa, że pasek zależy od foo i robi to
przed zrobieniem
Osoba wpisująca „make bar” nie musi wiedzieć, że pasek zależy od foo. Wstrzyknięto zależność między „make bar” a gcc.
Głównym celem poziomu pośredniego jest nie tylko przekazywanie zależności do konstruktora, ale także lista wszystkich zależności w jednym miejscu i ukrycie ich przed koderem (nie zmuszanie kodera do ich dostarczenia).
Zwykle poziom pośredni zapewnia fabryki budowanych obiektów, które muszą spełniać rolę, którą musi spełniać każdy żądany typ obiektu. Jest tak, ponieważ mając poziom pośredni, który ukrywa szczegóły budowy, poniosłeś już karę abstrakcji nałożoną przez fabryki, więc równie dobrze możesz korzystać z fabryk.
źródło
Wstrzykiwanie zależności oznacza sposób (właściwie dowolny sposób ), aby jedna część kodu (np. Klasa) miała dostęp do zależności (innych części kodu, np. Innych klas, od których to zależy) w sposób modułowy, bez ich zakodowania (więc można je dowolnie zmieniać lub zastępować, a nawet w razie potrzeby ładować w innym czasie)
(i ps, tak, to stało się zbyt hiper-25-calową nazwą dla raczej prostej koncepcji) , moje
.25
centyźródło
Wiem, że jest już wiele odpowiedzi, ale znalazłem to bardzo pomocne: http://tutorials.jenkov.com/dependency-injection/index.html
Bez zależności:
Zależność:
Zauważ, jak
DataSourceImpl
instancja jest przenoszona do konstruktora. Konstruktor przyjmuje cztery parametry, które są czterema wartościami potrzebnymi przezDataSourceImpl
. ChociażMyDao
klasa nadal zależy od tych czterech wartości, sama nie spełnia już tych zależności. Są dostarczane przez dowolną klasę tworzącąMyDao
instancję.źródło
Wstrzykiwanie zależności jest jednym z możliwych rozwiązań, które można ogólnie nazwać wymogiem „zaciemniania zależności”. Obfuskacja zależności jest metodą usuwania „oczywistej” natury z procesu zapewniania zależności klasie, która tego wymaga, a zatem zaciemniania, w pewien sposób, udostępniania wspomnianej zależności tej klasie. To niekoniecznie jest zła rzecz. W rzeczywistości, zaciemniając sposób, w jaki zależność jest przekazywana do klasy, wówczas coś poza klasą jest odpowiedzialne za tworzenie zależności, co oznacza, że w różnych scenariuszach inna implementacja zależności może być dostarczona do klasy bez wprowadzania żadnych zmian do klasy. Jest to doskonałe do przełączania między trybem produkcyjnym a testowym (np. Przy użyciu zależności „próbnej” usługi).
Niestety wadą jest to, że niektórzy ludzie założyli, że potrzebujesz specjalistycznego frameworka do zaciemniania zależności i że jesteś w jakiś sposób „mniejszym” programistą, jeśli zdecydujesz się nie używać do tego konkretnego frameworka. Kolejnym, niezwykle niepokojącym mitem, uważanym przez wielu, jest to, że zastrzyk uzależnienia jest jedynym sposobem na osiągnięcie zaciemnienia zależności. Jest to wyraźnie i historycznie i oczywiście w 100% błędne, ale będziesz miał trudności z przekonaniem niektórych osób, że istnieją alternatywy dla zastrzyku uzależnienia dla twoich wymagań zaciemniania zależności.
Programiści rozumieli wymóg zaciemniania zależności od lat i wiele alternatywnych rozwiązań ewoluowało zarówno przed, jak i po wymyśleniu zastrzyku zależności. Istnieją wzorce fabryczne, ale istnieje także wiele opcji wykorzystujących ThreadLocal, w których nie jest wymagane wstrzykiwanie do konkretnej instancji - zależność jest skutecznie wstrzykiwana do wątku, co ma tę zaletę, że udostępnia obiekt (za pomocą wygodnych metod statycznego pobierania) do dowolnegoklasa, która tego wymaga, bez konieczności dodawania adnotacji do klas, które tego wymagają, i skonfigurowania skomplikowanego „kleju” XML, aby tak się stało. Kiedy twoje zależności są wymagane do trwałości (JPA / JDO lub cokolwiek innego), pozwala to osiągnąć „tranaparent uporczywość” znacznie łatwiej i dzięki modelom domen i klasom modeli biznesowych złożonym wyłącznie z POJO (tj. Bez specyficznych ram / zablokowanych w adnotacjach).
źródło
Z książki „ Well-Grounded Java Developer: Istotne techniki programowania Java 7 i polyglot
źródło
Zanim przejdę do opisu technicznego, najpierw zwizualizuj go na przykładzie z życia, ponieważ znajdziesz wiele technicznych rzeczy do nauczenia się wstrzykiwania zależności, ale maksymalny czas, jaki ludzie tacy jak ja, nie mogą zrozumieć podstawowej koncepcji tego.
Na pierwszym zdjęciu Załóżmy, że masz fabrykę samochodów z wieloma jednostkami. Samochód jest faktycznie wbudowany w zespół montażowy, ale potrzebuje silnika , siedzeń oraz kół . Więc jednostki montażowej zależy od tych wszystkich jednostek i są Zależności fabryki.
Możesz czuć, że utrzymanie wszystkich zadań w tej fabryce jest zbyt skomplikowane, ponieważ wraz z głównym zadaniem (Montaż samochodu w zespole montażowym) musisz skupić się również na innych jednostkach . Utrzymanie jest teraz bardzo kosztowne, a budynek fabryki jest ogromny, więc możesz wziąć dodatkowe dolary do wynajęcia.
Teraz spójrz na drugie zdjęcie. Jeśli znajdziesz firmy oferujące tanie koła , siedzenia i silnik, które są tańsze niż koszty własnej produkcji, nie musisz robić ich w swojej fabryce. Możesz teraz wynająć mniejszy budynek tylko dla swojego zespołu montażowego, co zmniejszy zadanie konserwacji i zmniejszy dodatkowe koszty wynajmu. Teraz możesz skupić się tylko na głównym zadaniu (montaż samochodu).
Teraz możemy powiedzieć, że wszystkie zależności do montażu samochodu są wstrzykiwane fabrycznie od dostawców . Jest to przykład rzeczywistego wtrysku zależności (DI) .
Innymi słowy, wstrzykiwanie zależności jest techniką, w której jeden obiekt (lub metoda statyczna) dostarcza zależności drugiego obiektu. Tak więc przeniesienie zadania tworzenia obiektu na inną osobę i bezpośrednie użycie zależności nazywa się wstrzykiwaniem zależności.
To pomoże ci teraz nauczyć DI z jakimś słowem techy. To pokaże, kiedy używać DI, a kiedy nie .
.
źródło
z książki Apress.Spring.Persistence.w.Hibernate.Oct.2010
źródło
Dependency Injection (DI) to jeden z Design Patterns, który wykorzystuje podstawową cechę OOP - relację jednego obiektu z innym obiektem. Podczas gdy dziedziczenie dziedziczy jeden obiekt, aby wykonać bardziej złożony i specyficzny inny obiekt, relacja lub powiązanie po prostu tworzy wskaźnik do innego obiektu z jednego obiektu za pomocą atrybutu. Moc DI jest połączona z innymi funkcjami OOP, podobnie jak interfejsy i ukrywanie kodu. Załóżmy, że mamy w bibliotece klienta (subskrybenta), który dla uproszczenia może wypożyczyć tylko jedną książkę.
Interfejs książki:
Następnie możemy mieć wiele rodzajów książek; jednym z nich jest fikcja:
Teraz subskrybent może mieć powiązanie z książką:
Wszystkie trzy klasy można ukryć dla własnej implementacji. Teraz możemy użyć tego kodu dla DI:
Istnieje wiele różnych sposobów użycia wstrzykiwania zależności. Możliwe jest połączenie go z Singletonem itp., Ale nadal w podstawowym przypadku jest to tylko skojarzenie realizowane przez utworzenie atrybutu typu obiektu w innym obiekcie. Przydatność polega tylko i wyłącznie na tym, że ten kod, który powinniśmy pisać od nowa, jest zawsze dla nas przygotowany i wykonywany. Właśnie dlatego DI jest tak ściśle powiązany z Inversion of Control (IoC), co oznacza, że nasz program przekazuje sterowanie innemu działającemu modułowi, który wykonuje wstrzykiwanie fasoli do naszego kodu. (Każdy obiekt, który można wstrzyknąć, może zostać podpisany lub uznany za Fasolę.) Na przykład wiosną robi się to poprzez utworzenie i inicjalizację ApplicationContextkontener, który działa dla nas. Po prostu w naszym kodzie tworzymy kontekst i wywołujemy inicjalizację ziaren. W tym momencie wstrzyknięcie zostało wykonane automatycznie.
źródło
Zastrzyk zależny dla 5-latków.
Kiedy idziesz i wyciągasz rzeczy z lodówki dla siebie, możesz powodować problemy. Możesz zostawić otwarte drzwi, możesz dostać coś, czego mama lub tata nie chcą, żebyś miał. Być może szukasz czegoś, czego nawet nie mamy lub które wygasło.
To, co powinieneś zrobić, to stwierdzenie potrzeby: „Potrzebuję czegoś do picia z lunchem”, a wtedy upewnimy się, że masz coś, kiedy usiądziesz i coś zjeść.
źródło
Od Christoffera Noringa, książki Pablo Deelemana „Learning Angular - Second Edition”:
„Gdy nasze aplikacje rosną i ewoluują, każda z naszych jednostek kodu będzie wewnętrznie wymagać wystąpień innych obiektów , które w świecie inżynierii oprogramowania są lepiej znane jako zależności . Działanie polegające na przekazywaniu takich zależności do zależnego klienta jest znane jako wstrzykiwanie , i pociąga za sobą także udział innej jednostki kodowej o nazwie iniektor . Inżektor będzie odpowiedzialny za tworzenie instancji i ładowanie systemu wymaganych zależnościdzięki czemu są gotowe do użycia od momentu pomyślnego wstrzyknięcia do klienta. Jest to bardzo ważne, ponieważ klient nie wie nic o tym, jak utworzyć własną zależność i jest świadomy tylko interfejsu, który implementuje w celu ich użycia ”.
Od: Anton Moiseev. książka „Angular Development with Typescript, wydanie drugie”.:
„Krótko mówiąc, DI pomaga ci pisać kod w luźny sposób i sprawia, że kod jest bardziej testowalny i można go ponownie wykorzystać .”
źródło
W prostych słowach wstrzykiwanie zależności (DI) to sposób na usunięcie zależności lub ścisłe połączenie między różnymi obiektami. Wstrzykiwanie zależności zapewnia spójne zachowanie każdego obiektu.
DI to implementacja zasady MKOl wiosny, która mówi „Nie dzwoń do nas, my zadzwonimy”. Za pomocą programisty wstrzykiwania zależności nie trzeba tworzyć obiektu przy użyciu nowego słowa kluczowego.
Obiekty są raz ładowane do kontenera Spring, a następnie ponownie ich używamy, gdy tylko ich potrzebujemy, pobierając te obiekty z kontenera Spring przy użyciu metody getBean (String beanName).
źródło
Zastrzyk zależności jest sercem koncepcji związanej z Spring Framework. Podczas tworzenia szkieletu dowolnego projektu sprężyna może odgrywać istotną rolę, a tutaj zastrzyk zależności pojawia się w dzbanie.
W rzeczywistości załóżmy, że w java stworzyłeś dwie różne klasy, takie jak klasa A i klasa B, i niezależnie od funkcji dostępnej w klasie B, której chcesz użyć w klasie A, więc w tym czasie można zastosować wstrzykiwanie zależności. gdzie możesz utworzyć skrzynkę obiektu jednej klasy w drugiej, w ten sam sposób możesz wstrzyknąć całą klasę w inną klasę, aby była dostępna. w ten sposób można przezwyciężyć zależność.
WTRYSK ZALEŻNOŚCI JEST PO PROSTU SKLEJANIE DWÓCH KLAS I W TYM SAMYM CZASIE UTRZYMYWANIE JEGO ODDZIELNIE.
źródło