oversigt
i denne artikel introducerer vi begreberne IoC (Inversion of Control) og DI (Afhængighedsinjektion), og vi vil derefter se på, hvordan disse implementeres i Spring frame .ork.,
yderligere læsning:
ledningsføring i foråret: @Auto .ired, @Resource og @Inject
@Component vs @Repository og @Service i foråret
Hvad er Inversion af kontrol?,
Inversion af kontrol er et princip inden for soft .are engineering, hvorved kontrollen af objekter eller dele af et program overføres til en container eller ramme. Det bruges oftest i forbindelse med objektorienteret programmering.i modsætning til traditionel programmering, hvor vores brugerdefinerede kode foretager opkald til et bibliotek, gør IoC det muligt for en ramme at tage kontrol over strømmen af et program og foretage opkald til vores brugerdefinerede kode. For at aktivere dette bruger rammer abstraktioner med yderligere adfærd indbygget., Hvis vi vil tilføje vores egen adfærd, er vi nødt til at udvide klasserne i rammen eller plugin vores egne klasser.,fordelene ved denne arkitektur er:
- afkobling af udførelsen af en opgave fra dens implementering
- gør det lettere at skifte mellem forskellige implementeringer
- større modularitet af et program
- større lethed ved at teste et program ved at isolere en komponent eller håne dens afhængigheder og lade komponenter kommunikere gennem kontrakter
Inversion af kontrol kan opnås gennem forskellige mekanismer, såsom: Strategidesign mønster, Service Locator mønster, fabrik mønster, og afhængighed injektion (di).,
Vi vil se på DI næste.
Hvad er Afhængighedsinjektion?
Afhængighedsinjektion er et mønster, hvorigennem IOC skal implementeres, hvor kontrollen inverteres, er indstillingen af objektets afhængigheder.
handlingen med at forbinde objekter med andre objekter eller “injicere” objekter i andre objekter udføres af en assembler snarere end af objekterne selv.,
Sådan opretter du en objektafhængighed i traditionel programmering:
public class Store { private Item item; public Store() { item = new ItemImpl1(); }}
i eksemplet ovenfor skal vi instantiere en implementering af Elementgrænsefladen i selve Butiksklassen.
Ved at bruge DI kan vi omskrive eksemplet uden at specificere implementeringen af det element, vi ønsker:
public class Store { private Item item; public Store(Item item) { this.item = item; }}
i de næste afsnit ser vi, hvordan vi kan levere implementeringen af element gennem metadata.,
både IOC og DI er enkle begreber, men har dybe konsekvenser i den måde, vi strukturerer vores systemer på, så de er værd at forstå godt.
Spring IoC-beholderen
en IOC-beholder er et almindeligt kendetegn ved rammer, der implementerer IOC.
i Spring frame .ork er IOC-beholderen repræsenteret af interface-Applikationenconte .t. Fjederbeholderen er ansvarlig for instantiering, konfiguration og samling af genstande kendt som bønner, samt styring af deres livscyklus.,
Foråret rammer giver flere implementeringer af ApplicationContext interface — ClassPathXmlApplicationContext og FileSystemXmlApplicationContext for selvstændige programmer, og WebApplicationContext for web-applikationer.
for at samle bønner bruger beholderen konfigurationsmetadata, som kan være i form af configurationml-konfiguration eller kommentarer.
Her er en måde at manuelt instantiere en container på:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
for at indstille elementattributten i eksemplet ovenfor kan vi bruge metadata., Derefter vil beholderen læse denne metadata og bruge den til at samle bønner ved kørsel.Afhængighedsindsprøjtning i foråret kan ske gennem konstruktører, settere eller felter.
Constructor-Baseret Afhængighed Injektion
I tilfælde af constructor-baseret dependency injection, container vil påberåbe sig en konstruktør med argumenter, der hver repræsenterer en afhængighed, vi ønsker at sætte.
forår løser hvert argument primært efter type, efterfulgt af navnet på attributten og indekset for flertydig., Lad os se konfigurationen af en bønne og dens afhængigheder ved hjælp af annotationer:
@ – Konfigurationsannotationen angiver, at klassen er en kilde til bønnedefinitioner. Vi kan også tilføje det til flere konfigurationsklasser.
@Bean annotation bruges på en metode til at definere en bønne. Hvis vi ikke angiver et brugerdefineret navn, vil bønnenavnet standard til metodenavnet.
for en bønne med standard singleton-omfanget kontrollerer foråret først, om der allerede findes en cachelagret forekomst af bønnen, og opretter kun en ny, hvis den ikke gør det., Hvis vi bruger prototypeomfanget, returnerer beholderen en ny bønne-instans for hvert metodekald.
en Anden måde at skabe konfiguration af bønnerne er gennem XML-konfiguration:
Setter-Baseret Afhængighed Injektion
For setter-baseret DI, vil beholderen kalder setter metoder i vores klasse, efter at en ikke-argument konstruktør eller ikke-argument statisk factory method til at instantiere bean., Lad os oprette denne konfiguration ved hjælp af annotationer:
@Beanpublic Store store() { Store store = new Store(); store.setItem(item1()); return store;}
Vi kan også bruge beansml til den samme konfiguration af bønner:
<bean class="org.baeldung.store.Store"> <property name="item" ref="item1" /></bean>
Konstruktørbaserede og setter-baserede injektionstyper kan kombineres til den samme bønne. Fjederdokumentationen anbefaler at bruge konstruktørbaseret injektion til obligatoriske afhængigheder og setter-baseret injektion til valgfri.
7., Felt-Baseret Afhængighed Injektion
I tilfælde af Felt-Baseret DI, vi kan injicere afhængigheder ved at markere dem med et @Autowired anmærkning:
public class Store { @Autowired private Item item; }
under opbygningen af det Store objekt, hvis der ikke er nogen konstruktør eller setter metode til at injicere det Element, bønner, beholder vil bruge refleksion til at injicere Varen i Butikken.
Vi kan også opnå dette ved hjælp af configurationml-konfiguration.,
Denne tilgang kunne se enklere og renere, men det anbefales ikke at bruge, fordi det har et par ulemper som:
- Denne metode bruger refleksion for at tilføre de afhængigheder, der er dyrere end constructor-baseret eller setter-baseret injektion
- Det er virkelig nemt at holde tilføje flere afhængigheder ved hjælp af denne tilgang. Hvis du brugte konstruktørinjektion med flere argumenter, ville det have fået os til at tro, at klassen gør mere end moren ting, der kan krænke princippet om enkelt ansvar.,
mere information om @Auto .ired annotation kan findes i ledninger i foråret artiklen.
Autoiringiring afhængigheder
ledninger gør det muligt for Fjederbeholderen automatisk at løse afhængigheder mellem samarbejdende bønner ved at inspicere de bønner, der er defineret.,
Der er fire tilstande af autowiring en bønne med en XML-konfiguration:
- nej: standard værdi – det betyder ingen autowiring bruges til bønnen, og vi er nødt til eksplicit navn afhængigheder
- byName: autowiring er gjort baseret på navnet på den ejendom, derfor Forår vil se til en bønne med samme navn som den egenskab, der skal indstilles
- byType: svarende til byName autowiring, kun baseret på typen af ejendom. Dette betyder, at foråret vil kigge efter en bønne med den samme type ejendom, der skal indstilles., Hvis der er mere end en bønne af den type, kaster rammen en undtagelse.,kan også injicere bønner ved hjælp af @Auto Autired annotation til autoiringiring efter type:
public class Store { @Autowired private Item item;}
Hvis der er mere end en bønne af samme type, kan vi bruge @Qualifualifier-annotationen til at henvise til en bønne ved navn:
public class Store { @Autowired @Qualifier("item1") private Item item;}
lad os nu Auto beansire bønner efter type gennem configurationml-konfiguration:
<bean class="org.baeldung.store.Store" autowire="byType"> </bean>
lad os derefter injicere en bønne navngivet genstand i genstandsegenskaben til store Bean ved navn gennem nameml:
<bean class="org.baeldung.store.ItemImpl1" /><bean class="org.baeldung.store.Store" autowire="byName"></bean>
Vi kan også tilsidesætte autoiringiring ved at definere afhængigheder eksplicit gennem konstruktørargumenter eller settere.,
La .y initialiserede bønner
som standard opretter og konfigurerer beholderen alle singleton bønner under initialisering. For at undgå dette kan du bruge attributten la .y-init med værdien true på bønnekonfigurationen:
<bean class="org.baeldung.store.ItemImpl1" lazy-init="true" />
som følge heraf initialiseres item1-bønnen kun, når den først anmodes om, og ikke ved opstart., Fordelen ved dette er hurtigere Initialiseringstid, men afvejningen er, at konfigurationsfejl kun kan opdages, efter at bønnen er anmodet om, hvilket kan være flere timer eller endda dage efter, at applikationen allerede har kørt.
konklusion
i denne artikel har vi præsenteret begreberne inversion af kontrol og afhængighedsinjektion og eksemplificeret dem i Spring frame .ork.
Du kan læse mere om disse begreber i Martin fo .lers artikler:
- Inversion af Kontrolbeholdere og Afhængighedsinjektionsmønsteret.,
- Inversion af kontrol