Uvod u inverziju upravljanja i ubrizgavanja ovisnosti s oprugom

1. Pregled

U ovom ćemo članku predstaviti koncepte IoC (inverzija upravljanja) i DI (ubrizgavanje ovisnosti), a zatim ćemo pogledati kako se oni provode u proljetnom okviru.

2. Što je inverzija kontrole?

Inverzija kontrole je princip u softverskom inženjerstvu kojim se kontrola objekata ili dijelova programa prenosi u spremnik ili okvir. Najčešće se koristi u kontekstu objektno orijentiranog programiranja.

Za razliku od tradicionalnog programiranja, u kojem naš prilagođeni kod poziva biblioteku, IoC omogućuje okvir koji preuzima kontrolu nad protokom programa i upućuje pozive našem prilagođenom kodu. Da bi to omogućili, okviri koriste apstrakcije s ugrađenim dodatnim ponašanjem. Ako želimo dodati vlastito ponašanje, trebamo proširiti klase okvira ili dodavati vlastite razrede.

Prednosti ove arhitekture su:

  • razdvajanje izvršenja zadatka od njegove provedbe
  • olakšavajući prebacivanje između različitih implementacija
  • veća modularnost programa
  • veća jednostavnost u testiranju programa izoliranjem komponente ili ismijavanjem njezinih ovisnosti i omogućavanjem komponentama da komuniciraju putem ugovora

Inverzija kontrole može se postići različitim mehanizmima kao što su: obrazac dizajna strategije, obrazac lokatora usluga, tvornički obrazac i ubrizgavanje ovisnosti (DI).

Sljedeći ćemo pogled na DI.

3. Što je injekcija ovisnosti?

Injekcija ovisnosti je obrazac kroz koji se implementira IoC, gdje je kontrola koja se invertira podešavanje ovisnosti objekta.

Čin povezivanja predmeta s drugim objektima ili "ubrizgavanja" predmeta u druge predmete obavlja asembler, a ne sami predmeti.

Evo kako biste stvorili ovisnost o objektima u tradicionalnom programiranju:

javna klasa Store {privatna stavka; javna trgovina () {item = new ItemImpl1 (); }}

U gornjem primjeru, moramo pokrenuti implementaciju Artikal sučelje unutar Spremi sama klasa.

Korištenjem DI-a možemo prepisati primjer bez navođenja provedbe Artikal da želimo:

javna klasa Store {privatna stavka; javna trgovina (stavka predmeta) {this.item = item; }}

U sljedećim odjeljcima vidjet ćemo kako možemo osigurati provedbu Artikal kroz metapodatke.

I IoC i DI jednostavni su koncepti, ali imaju duboke implikacije na način na koji strukturiramo naše sustave, pa ih vrijedi dobro razumjeti.

4. Proljetni IoC kontejner

IoC spremnik uobičajena je karakteristika okvira koji implementiraju IoC.

U okviru Spring, IoC spremnik predstavljen je sučeljem ApplicationContext. Spremnik Spring odgovoran je za instanciranje, konfiguriranje i sastavljanje objekata poznatih kao grah, kao i upravljanje njihovim životnim ciklusom.

Proljetni okvir pruža nekoliko implementacija ApplicationContext sučelje - ClassPathXmlApplicationContext i FileSystemXmlApplicationContext za samostalne aplikacije i WebApplicationContext za web aplikacije.

Da bi se sastavio grah, spremnik koristi konfiguracijske metapodatke, koji mogu biti u obliku XML konfiguracije ili bilješki.

Evo jednog načina ručnog instanciranja spremnika:

ApplicationContext context = new ClassPathXmlApplicationContext ("applicationContext.xml");

Za postavljanje artikal atribut u gornjem primjeru, možemo koristiti metapodatke. Zatim će spremnik pročitati ove metapodatke i upotrijebiti ih za sastavljanje graha tijekom izvođenja.

Injektiranje ovisnosti u proljeće može se izvršiti putem konstruktora, postavljača ili polja.

5. Injekcija ovisnosti na temelju konstruktora

U slučaju ubrizgavanja ovisnosti na temelju konstruktora, spremnik će pozvati konstruktor s argumentima koji svaki predstavljaju ovisnost koju želimo postaviti.

Spring razrješava svaki argument prvenstveno po tipu, nakon čega slijedi ime atributa i indeks radi višeznačnosti. Pogledajmo konfiguraciju graha i njegove ovisnosti pomoću napomena:

@Configuration javna klasa AppConfig {@Bean public Item item1 () {return new ItemImpl1 (); } @Bean public Store store () {return new Store (item1 ()); }}

The @Konfiguracija napomena označava da je klasa izvor definicija graha. Također, možemo ga dodati u više klasa konfiguracije.

The @Grah anotacija se koristi na metodi za definiranje graha. Ako ne odredimo prilagođeni naziv, naziv zrna bit će zadano za naziv metode.

Za grah sa zadanim jednokrevetna opseg, Spring prvo provjerava postoji li predmemorirana instanca graha i stvara novu samo ako ne postoji. Ako koristimo prototip opseg, spremnik vraća novu instancu graha za svaki poziv metode.

Drugi način za stvaranje konfiguracije graha je putem XML konfiguracije:

6. Ubrizgavanje ovisnosti temeljeno na Setteru

Za DI koji se temelji na postavljaču, spremnik će pozvati metode postavljača iz naše klase, nakon što pozove konstruktor bez argumenta ili statičku tvorničku metodu bez argumenta za instanciju graha. Stvorimo ovu konfiguraciju pomoću bilješki:

@Bean public Store store () {Store store = new Store (); store.setItem (item1 ()); povratna trgovina; }

Također možemo koristiti XML za istu konfiguraciju graha:

Vrste ubrizgavanja na bazi konstruktora i setera mogu se kombinirati za isti grah. Proljetna dokumentacija preporučuje upotrebu ubrizgavanja na temelju konstruktora za obvezne ovisnosti i ubrizgavanje na temelju postavljača za neobavezne.

7. Na terenu Injekcija ovisnosti

U slučaju terenskog DI-a, ovisnosti možemo ubrizgati označavajući ih znakom @Autowired napomena:

trgovina javne klase {@Autowired private item item; }

Tijekom konstrukcije Spremi objekt, ako ne postoji konstruktor ili metoda postavljača za ubrizgavanje Artikal grah, spremnik će upotrijebiti odraz za ubrizgavanje Artikal u Spremi.

To također možemo postići pomoću XML konfiguracije.

Ovaj pristup može izgledati jednostavnije i čišće, ali se ne preporučuje za upotrebu jer ima nekoliko nedostataka kao što su:

  • Ova metoda koristi refleksiju za ubrizgavanje ovisnosti, što je skuplje od ubrizgavanja temeljenog na konstruktoru ili postavljaču
  • Stvarno je lako nastaviti dodavati više ovisnosti koristeći ovaj pristup. Da ste koristili ubrizgavanje konstruktora, višestruki bi nas argumenti natjerali da pomislimo da klasa radi više od jedne stvari koja može prekršiti princip jedinstvene odgovornosti.

Više informacija o @Autowired napomenu možete pronaći u članku Ožičenje u proljeće.

8. Ovisnosti automatskog ožičenja

Ožičenje omogućuje spremniku Spring da automatski riješi ovisnosti između graha koji surađuju pregledavajući grah koji je definiran.

Postoje četiri načina automatskog povezivanja graha pomoću XML konfiguracije:

  • Ne: zadana vrijednost - to znači da se za grah ne koristi automatsko ožičenje i moramo izričito imenovati ovisnosti
  • imenom: automatsko ožičenje vrši se na temelju naziva nekretnine, stoga će Spring tražiti grah s istim nazivom kao i svojstvo koji treba postaviti
  • byType: slično kao imenom automatsko ožičenje, samo na temelju vrste nekretnine. To znači da će Spring potražiti grah s istim tipom svojstva koje treba postaviti. Ako postoji više od jednog graha te vrste, okvir daje iznimku.
  • konstruktor: automatsko ožičenje vrši se na temelju argumenata konstruktora, što znači da će Spring tražiti grah iste vrste kao i argumenti konstruktora

Na primjer, automatski povežemo stavka1 grah definiran gore prema tipu u pohraniti grah:

@Bean (autowire = Autowire.BY_TYPE) javna klasa Store {private item item; javni setItem (Stavka stavke) {this.item = stavka; }}

Grah također možemo ubrizgati pomoću @Autowired napomena za automatsko ožičenje prema tipu:

trgovina javne klase {@Autowired private item item; }

Ako postoji više zrna iste vrste, možemo koristiti @Kvalifikator napomena uz pozivanje na grah imenom:

trgovina javnih klasa {@Autowired @Qualifier ("item1") privatna stavka predmeta; }

Ajmo sada automatski spojiti grah po tipu kroz XML konfiguraciju:

Dalje, ubrizgajmo grah s imenom artikal u artikal vlasništvo pohraniti grah po imenu kroz XML:

Također možemo nadjačati automatsko povezivanje tako da eksplicitno definiramo ovisnosti putem argumenata konstruktora ili postavljača.

9. Lijeni inicijalizirani grah

Prema zadanim postavkama spremnik stvara i konfigurira sve pojedinačne grahove tijekom inicijalizacije. Da biste to izbjegli, možete koristiti lijen-init atribut s vrijednošću pravi na konfiguraciji graha:

Kao posljedica toga stavka1 bean će se inicijalizirati samo kad se prvi put zatraži, a ne prilikom pokretanja. Prednost toga je brže vrijeme inicijalizacije, ali kompromis je u tome što se pogreške u konfiguraciji mogu otkriti tek nakon što se zatraži grah, što može proći nekoliko sati ili čak dana nakon što je aplikacija već pokrenuta.

10. Zaključak

U ovom smo članku predstavili koncepte inverzije upravljanja i ubrizgavanja ovisnosti i prikazali ih u proljetnom okviru.

O ovim konceptima možete pročitati više u člancima Martina Fowlera:

  • Inverzija upravljačkih spremnika i obrazac ubrizgavanja ovisnosti.
  • Inverzija kontrole

A više o proljetnim implementacijama IoC-a i DI-a možete saznati u referentnoj dokumentaciji Spring Framework.