Kabling på våren: @Autowired, @Resource og @Inject

1. Oversikt

Denne artikkelen om vårens rammeverk vil demonstrere bruken av merknader relatert til avhengighetsinjeksjon, nemlig @Ressurs, @Injiser, og @Autowired kommentarer. Disse kommentarene gir klasser en deklarativ måte å løse avhengigheter på. For eksempel:

@Autowired ArbitraryClass arbObject;

i motsetning til å instantiere dem direkte (den tvingende måten), for eksempel:

ArbitraryClass arbObject = ny ArbitraryClass ();

To av de tre kommentarene tilhører Java-utvidelsespakken: javax.annotation.Resource og javax.inject.Inject. De @Autowired merknader tilhører org.springframework.beans.factory.annotation pakke.

Hver av disse merknadene kan løse avhengigheter enten ved feltinjeksjon eller ved setterinjeksjon. Et forenklet, men praktisk eksempel vil bli brukt for å demonstrere skillet mellom de tre kommentarene, basert på utførelsesbanene som tas av hver kommentar.

Eksemplene vil fokusere på hvordan du bruker de tre injeksjonsnotatene under integrasjonstesting. Avhengigheten som kreves av testen kan enten være en vilkårlig fil eller en vilkårlig klasse.

2. Den @Ressurs ENnotasjon

De @Ressurs merknader er en del av JSR-250 merkesamlingen og er pakket med Jakarta EE. Denne merknaden har følgende kjøringsbaner, oppført etter forrang:

  1. Match etter navn
  2. Match etter type
  3. Kamp etter kvalifiseringskamp

Disse utførelsesbanene gjelder både setter og feltinjeksjon.

2.1. Feltinjeksjon

Å løse avhengigheter ved feltinjeksjon oppnås ved å kommentere en forekomstvariabel med @Ressurs kommentar.

2.1.1. Match etter navn

Integreringstesten som brukes til å demonstrere feltinjeksjon etter navn, er oppført som følger:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestResourceNameType.class) public class FieldResourceInjectionIntegrationTest {@Resource (name = "namedFile") private standardfil @Test offentlig ugyldighet gittResourceAnnotation_WhenOnField_ThenDependencyValid () {assertNotNull (defaultFile); assertEquals ("namedFile.txt", defaultFile.getName ()); }}

La oss gå gjennom koden. I FieldResourceInjectionTest integrasjonstest, på linje 7, oppløsningen av avhengigheten ved navn oppnås ved å sende inn bønnenavnet som en attributtverdi til @Ressurs kommentar:

@Resource (name = "namedFile") privat fil defaultFile;

Denne konfigurasjonen løser avhengigheter ved å utføre banen for samsvar etter navn. Bønnen heterFil må defineres i ApplicationContextTestResourceNameType applikasjonskontekst.

Merk at bønne-ID-en og den tilsvarende referanseattributtverdien må samsvare med:

@Configuration public class ApplicationContextTestResourceNameType {@Bean (name = "namedFile") public File namedFile () {File namedFile = new File ("namedFile.txt"); retur namedFile; }}

Unnlatelse av å definere bønnen i applikasjonssammenheng vil resultere i a org.springframework.beans.factory.NoSuchBeanDefinitionException blir kastet. Dette kan demonstreres ved å endre attributtverdien overført til @Bønne kommentar, i ApplicationContextTestResourceNameType applikasjonskontekst; eller endre attributtverdien overført til @Ressurs kommentar, i FieldResourceInjectionTest integrasjonstest.

2.1.2. Match etter type

For å demonstrere kjøringsbanen for samsvar etter type, er det bare å fjerne attributtverdien på linje 7 i FieldResourceInjectionTest integrasjonstest slik at den ser ut som følger:

@Resource private File defaultFile;

og kjør testen igjen.

Testen vil fortsatt bestå fordi hvis @Ressurs kommentar mottar ikke et bønnenavn som attributtverdi, Spring Framework vil fortsette med neste prioritetsnivå, match-for-type, for å prøve å løse avhengigheten.

2.1.3. Kamp etter kvalifiseringskamp

For å demonstrere kjøringsbanen match-by-qualifier, vil testscenarioet for integrering bli endret slik at det er to bønner definert i ApplicationContextTestResourceQualifier applikasjonskontekst:

@Configuration public class ApplicationContextTestResourceQualifier {@Bean (name = "defaultFile") public File defaultFile () {File defaultFile = new File ("defaultFile.txt"); return defaultFile; } @Bean (name = "namedFile") public File namedFile () {File namedFile = new File ("namedFile.txt"); retur namedFile; }}

De QualifierResourceInjectionTest integrasjonstest vil bli brukt til å demonstrere avhengighetsoppløsning for kamp for kvalifisering. I dette scenariet må en bestemt bønneavhengighet injiseres i hver referansevariabel:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestResourceQualifier.class) offentlig klasse QualifierResourceInjectionIntegrationTest {@Resource private File dependency1; @Resource private Filavhengighet2; @Test offentlig ugyldighet gittResourceAnnotation_WhenField_ThenDependency1Valid () {assertNotNull (avhengighet1); assertEquals ("defaultFile.txt", dependency1.getName ()); } @Test offentlig ugyldighet gittResourceQualifier_WhenField_ThenDependency2Valid () {assertNotNull (avhengighet2); assertEquals ("namedFile.txt", dependency2.getName ()); }}

Kjør integrasjonstesten, og en org.springframework.beans.factory.NoUniqueBeanDefinitionException blir kastet. Dette unntaket blir kastet fordi applikasjonskonteksten har funnet to bønnedefinisjoner av typen Fil, og det er forvirret om hvilken bønne som skal løse avhengigheten.

For å løse dette problemet, se linje 7 til linje 10 i QualifierResourceInjectionTest integrasjonstest:

@Resource private Filavhengighet1; @Resource private Filavhengighet2;

og legg til følgende kodelinjer:

@Qualifier ("defaultFile") @Qualifier ("namedFile")

slik at kodeblokken ser slik ut:

@Resource @Qualifier ("defaultFile") privat Filavhengighet1; @Resource @Qualifier ("namedFile") privat Filavhengighet2;

Kjør integrasjonstesten igjen, denne gangen skal den bestå. Målet med denne testen var å demonstrere at selv om det er flere bønner definert i en applikasjonssammenheng, er @Kvalifiserende kommentar fjerner enhver forvirring ved å la spesifikke avhengigheter injiseres i en klasse.

2.2. Setter Injection

Utførelsesbanene som tas når du injiserer avhengigheter på et felt, gjelder for setterbasert injeksjon.

2.2.1. Match etter navn

Den eneste forskjellen er MethodResourceInjectionTest integrasjonstest har en settermetode:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestResourceNameType.class) public class MethodResourceInjectionIntegrationTest {private File defaultFile; @Resource (name = "namedFile") beskyttet ugyldig setDefaultFile (File defaultFile) {this.defaultFile = defaultFile; } @Test offentlig ugyldig givenResourceAnnotation_WhenSetter_ThenDependencyValid () {assertNotNull (defaultFile); assertEquals ("namedFile.txt", defaultFile.getName ()); }}

Å løse avhengigheter ved setterinjeksjon gjøres ved å kommentere en referansevariabels tilsvarende settermetode. Gi navnet på bønneavhengigheten som attributtverdi til @Ressurs kommentar:

privat Fil defaultFile; @Resource (name = "namedFile") beskyttet ugyldig setDefaultFile (File defaultFile) {this.defaultFile = defaultFile; }

De namedFile bønneavhengighet vil bli gjenbrukt i dette eksemplet. Bønnenavnet og den tilsvarende attributtverdien må samsvare.

Kjør integrasjonstesten som den er, og den vil bestå.

For å se at avhengigheten faktisk ble løst av kjøringsbanen for samsvar etter navn, endrer du attributtverdien sendt til @Ressurs kommentar til en verdi du ønsker og kjør testen på nytt. Denne gangen vil testen mislykkes med en NoSuchBeanDefinitionException.

2.2.2. Match etter type

For å demonstrere setterbasert, samsvar etter type utførelse, vil vi bruke MethodByTypeResourceTest integrasjonstest:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestResourceNameType.class) offentlig klasse MethodByTypeResourceIntegrationTest {private File defaultFile; @Resource-beskyttet ugyldighet setDefaultFile (File defaultFile) {this.defaultFile = defaultFile; } @Test offentlig ugyldighet gittResourceAnnotation_WhenSetter_ThenValidDependency () {assertNotNull (defaultFile); assertEquals ("namedFile.txt", defaultFile.getName ()); }}

Kjør denne testen som den er, og den vil bestå.

For å bekrefte at Fil avhengighet ble faktisk løst av samsvarstype-utførelsesbanen, endre klassetypen til defaultFile variabel til en annen klassetype som String. Utfør MethodByTypeResourceTest integrasjonstest igjen og denne gangen a NoSuchBeanDefinitionException vil bli kastet.

Unntaket bekrefter at samsvar etter type faktisk ble brukt til å løse Fil avhengighet. De NoSuchBeanDefinitionException bekrefter at referansevariabelnavnet ikke trenger å matche bønnenavnet. I stedet avhenger avhengighetsoppløsning av bønnens klassetype som samsvarer med referansevariabelens klassetype.

2.2.3. Kamp etter kvalifiseringskamp

De MethodByQualifierResourceTest integrasjonstest vil bli brukt til å demonstrere kjøringsbanen match-by-qualifier:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestResourceQualifier.class) offentlig klasse MethodByQualifierResourceIntegrationTest {private File arbDependency; private File anotherArbDependency; @Test offentlig ugyldighet givenResourceQualifier_WhenSetter_ThenValidDependencies () {assertNotNull (arbDependency); assertEquals ("namedFile.txt", arbDependency.getName ()); assertNotNull (anotherArbDependency); assertEquals ("defaultFile.txt", anotherArbDependency.getName ()); } @Resource @Qualifier ("namedFile") offentlig tomrom setArbDependency (File arbDependency) {this.arbDependency = arbDependency; } @Resource @Qualifier ("defaultFile") offentlig ugyldig setAnotherArbDependency (File anotherArbDependency) {this.anotherArbDependency = anotherArbDependency; }}

Målet med denne testen er å demonstrere at selv om flere bønneimplementeringer av en bestemt type er definert i en applikasjonssammenheng, a @Kvalifiserende merknader kan brukes sammen med @Ressurs kommentar for å løse en avhengighet.

I likhet med feltbasert avhengighetsinjeksjon, hvis det er definert flere bønner i en applikasjonskontekst, a NoUniqueBeanDefinitionException kastes hvis nei @Kvalifiserende kommentar brukes til å spesifisere hvilken bønne som skal brukes til å løse avhengigheter.

3. Den @Injiser Kommentar

De @Injiser merknader tilhører JSR-330-merkesamlingen. Denne merknaden har følgende kjøringsbaner, oppført etter forrang:

  1. Match etter type
  2. Kamp etter kvalifiseringskamp
  3. Match etter navn

Disse utførelsesbanene gjelder både for setter og feltinjeksjon. For å få tilgang til @Injiser kommentar, den javax.inject biblioteket må deklareres som en Gradle eller Maven avhengighet.

For Gradle:

testCompile gruppe: 'javax.inject', navn: 'javax.inject', versjon: '1'

For Maven:

 javax.inject javax.inject 1 

3.1. Feltinjeksjon

3.1.1. Match etter type

Eksempel på integrasjonstest vil bli modifisert for å bruke en annen type avhengighet, nemlig Vilkårlig avhengighet klasse. De Vilkårlig avhengighet klasseavhengighet tjener bare som en enkel avhengighet og har ingen ytterligere betydning. Den er oppført som følger:

@Komponent offentlig klasse ArbitraryDependency {private final String label = "arbitrær avhengighet"; offentlig String toString () {returetikett; }}

De FieldInjectTest den aktuelle integrasjonstesten er oppført som følger:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestInjectType.class) public class FieldInjectIntegrationTest {@Inject private ArbitraryDependency fieldInjectDependency; @Test offentlig ugyldighet givenInjectAnnotation_WhenOnField_ThenValidDependency () {assertNotNull (fieldInjectDependency); assertEquals ("vilkårlig avhengighet", fieldInjectDependency.toString ()); }}

i motsetning til @Ressurs kommentar, som løser avhengigheter etter navn først; standard oppførsel av @Injiser kommentar løser avhengigheter etter type.

Dette betyr at selv om et klassereferansevariabelnavn skiller seg fra bønnenavnet, vil avhengigheten fortsatt løses, forutsatt at bønnen er definert i applikasjonssammenheng. Legg merke til hvordan referansevariabelnavnet i følgende test:

@Inject private ArbitraryDependency fieldInjectDependency;

skiller seg fra bønnenavnet som er konfigurert i applikasjonssammenheng:

@Bean public ArbitraryDependency injectDependency () {ArbitraryDependency injectDependency = new ArbitraryDependency (); retur injisere Avhengighet; }

og når testen utføres, er den i stand til å løse avhengigheten.

3.1.2. Kamp etter kvalifiseringskamp

Men hva om det er flere implementeringer av en bestemt klassetype, og en bestemt klasse krever en bestemt bønne? La oss endre eksemplet på integrasjonstesting slik at det kreves en annen avhengighet.

I dette eksemplet underklasser vi Vilkårlig avhengighet klasse, brukt i samsvar for eksempel-eksemplet, for å lage Nok en vilkårlig avhengighet klasse:

offentlig klasse AnotherArbitraryDependency utvider ArbitraryDependency {private final String label = "Another Arbitrary Dependency"; offentlig String toString () {returetikett; }}

Målet med hvert testtilfelle er å sikre at hver avhengighet injiseres riktig i hver referansevariabel:

@Inject private ArbitraryDependency defaultDependency; @Injiser privat vilkårlig avhengighet kalt avhengighet;

De FieldQualifierInjectTest integrasjonstest som brukes til å demonstrere kamp etter kvalifikator, er oppført som følger:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestInjectQualifier.class) offentlig klasse FieldQualifierInjectIntegrationTest {@ Inject private ArbitraryDependency defaultDependency; @Injiser privat vilkårlig avhengighet kalt avhengighet; @Test offentlig ugyldighet givenInjectQualifier_WhenOnField_ThenDefaultFileValid () {assertNotNull (standardavhengighet); assertEquals ("vilkårlig avhengighet", defaultDependency.toString ()); } @Test offentlig ugyldighet givenInjectQualifier_WhenOnField_ThenNamedFileValid () {assertNotNull (standardavhengighet); assertEquals ("Nok en vilkårlig avhengighet", kaltDependency.toString ()); }}

Hvis det er flere implementeringer av en bestemt klasse i applikasjonssammenheng og FieldQualifierInjectTest integrasjonstest prøver å injisere avhengighetene på den måten som er oppført nedenfor:

@Inject private ArbitraryDependency defaultDependency; @Injiser privat vilkårlig avhengighet kalt avhengighet;

en NoUniqueBeanDefinitionException vil bli kastet.

Å kaste dette unntaket er Spring Frameworks måte å påpeke at det er flere implementeringer av en bestemt klasse, og det er forvirret om hvilken man skal bruke. For å belyse forvirringen, gå til linje 7 og 10 i FieldQualifierInjectTest integrasjonstest:

@Inject private ArbitraryDependency defaultDependency; @Injiser privat vilkårlig avhengighet kalt avhengighet;

gi det nødvendige bønnenavnet til @Kvalifiserende kommentar, som brukes sammen med @Injiser kommentar. Kodeblokken ser nå ut som følger:

@Inject @Qualifier ("defaultFile") private ArbitraryDependency defaultDependency; @Inject @Qualifier ("namedFile") privat vilkårlig avhengighet navngitt avhengighet;

De @Kvalifiserende kommentar forventer en streng samsvar når du mottar et bønnenavn. Forsikre deg om at bønnenavnet overføres til Kvalifisering riktig, ellers, a NoUniqueBeanDefinitionException vil bli kastet. Kjør testen igjen, og denne gangen skal den bestå.

3.1.3. Match etter navn

De FieldByNameInjectTest integrasjonstest som brukes til å demonstrere samsvar etter navn, ligner på kjøringsbane for samsvar etter type. Den eneste forskjellen er at det nå kreves en bestemt bønne, i motsetning til en bestemt type. I dette eksemplet underklasser vi Vilkårlig avhengighet klasse igjen for å produsere Ennå en annen vilkårlig avhengighet klasse:

offentlig klasse YetAnotherArbitraryDependency utvider ArbitraryDependency {private final String label = "Yet Another Arbitrary Dependency"; offentlig String toString () {returetikett; }}

For å demonstrere kjøringsbanen for samsvar etter navn, bruker vi følgende integrasjonstest:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestInjectName.class) public class FieldByNameInjectIntegrationTest {@Inject @Named ("yetAnotherFieldInjectDependency) @Test offentlig ugyldighet givenInjectQualifier_WhenSetOnField_ThenDependencyValid () {assertNotNull (yetAnotherFieldInjectDependency); assertEquals ("Yet Another Arbitrary Dependency", yetAnotherFieldInjectDependency.toString ()); }}

Søknadskonteksten er oppført som følger:

@Configuration public class ApplicationContextTestInjectName {@Bean public ArbitraryDependency yetAnotherFieldInjectDependency () {ArbitraryDependency yetAnotherFieldInjectDependency = new YetAnotherArbitraryDependency (); return yetAnotherFieldInjectDependency; }}

Kjør integrasjonstesten som den er, så vil den bestå.

For å bekrefte at avhengigheten faktisk ble injisert av kjøringsbanen for samsvar etter navn, endrer du verdien, yetAnotherFieldInjectDependency, som ble gitt videre til @Named kommentar til et annet navn du ønsker. Kjør testen igjen - denne gangen, a NoSuchBeanDefinitionException blir kastet.

3.2. Setter Injection

Setterbasert injeksjon for @Injiser merknader ligner tilnærmingen som brukes til @Ressurs setterbasert injeksjon. I stedet for å kommentere referansevariabelen, blir den tilsvarende settermetoden kommentert. Utførelsesbanene fulgt av feltbasert avhengighetsinjeksjon gjelder også for setterbasert injeksjon.

4. Den @Autowired Kommentar

Oppførselen til @Autowired merknader ligner på @Injiser kommentar. Den eneste forskjellen er at @Autowired kommentar er en del av vårens rammeverk. Denne merknaden har samme kjøringsbaner som @Injiser kommentar, oppført i rekkefølge:

  1. Match etter type
  2. Kamp etter kvalifiseringskamp
  3. Match etter navn

Disse utførelsesbanene gjelder både for setter og feltinjeksjon.

4.1. Feltinjeksjon

4.1.1. Match etter type

Eksemplet på integrasjonstesting brukt til å demonstrere @Autowired match-by-type kjøringsbane vil være lik testen som ble brukt til å demonstrere @Injiser match-by-type kjøringsbane. De FieldAutowiredTest integrasjonstest som brukes til å demonstrere samsvar etter type ved hjelp av @Autowired merknader er oppført som følger:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestAutowiredType.class) public class FieldAutowiredIntegrationTest {@Autowired private ArbitraryDependency fieldDependency; @Test offentlig ugyldighet givenAutowired_WhenSetOnField_ThenDependencyResolved () {assertNotNull (fieldDependency); assertEquals ("vilkårlig avhengighet", fieldDependency.toString ()); }}

Søknadskonteksten for denne integrasjonstesten er oppført som følger:

@Configuration public class ApplicationContextTestAutowiredType {@Bean public ArbitraryDependency autowiredFieldDependency () {ArbitraryDependency autowiredFieldDependency = new ArbitraryDependency (); returner autowiredFieldDependency; }}

Målet med integrasjonstesten er å demonstrere at samsvar etter type har forrang over de andre utførelsesbanene. Merknad på linje 8 i FieldAutowiredTest integrasjonstest hvordan referansevariabelnavnet:

@Autowired private ArbitraryDependency fieldDependency;

er forskjellig fra bønnenavnet i applikasjonssammenheng:

@Bean public ArbitraryDependency autowiredFieldDependency () {ArbitraryDependency autowiredFieldDependency = new ArbitraryDependency (); returner autowiredFieldDependency; }

Når testen kjøres, vil den bestå.

For å bekrefte at avhengigheten faktisk ble løst ved å bruke kjøringsbanen for samsvar etter type, endrer du typen feltavhengighet referansevariabel og kjør integrasjonstesten igjen. Denne gangen rundt FieldAutowiredTest integrasjonstest må mislykkes, med en NoSuchBeanDefinitionException blir kastet. Dette bekrefter at samsvar etter type ble brukt for å løse avhengigheten.

4.1.2. Kamp etter kvalifiseringskamp

Hva om du står overfor en situasjon der flere bønneimplementeringer er definert i applikasjonssammenheng, som den som er oppført nedenfor:

@Configuration public class ApplicationContextTestAutowiredQualifier {@Bean public ArbitraryDependency autowiredFieldDependency () {ArbitraryDependency autowiredFieldDependency = new ArbitraryDependency (); returner autowiredFieldDependency; } @Bean public ArbitraryDependency anotherAutowiredFieldDependency () {ArbitraryDependency anotherAutowiredFieldDependency = new AnotherArbitraryDependency (); returner en annenAutowiredFieldDependency; }}

Hvis den FieldQualifierAutowiredTest integrasjonstest, oppført nedenfor, kjøres:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestAutowiredQualifier.class) public class FieldQualifierAutowiredIntegrationTest {@Autowired private ArbitraryDependency fieldDependent; @Autowired private ArbitraryDependency fieldDependency2; @Test offentlig ugyldighet givenAutowiredQualifier_WhenOnField_ThenDep1Valid () {assertNotNull (fieldDependency1); assertEquals ("vilkårlig avhengighet", fieldDependency1.toString ()); } @Test offentlig ugyldighet givenAutowiredQualifier_WhenOnField_ThenDep2Valid () {assertNotNull (fieldDependency2); assertEquals ("En annen vilkårlig avhengighet", feltavhengighet2.toString ()); }}

en NoUniqueBeanDefinitionException vil bli kastet.

Unntaket skyldes tvetydigheten forårsaket av de to bønnene som er definert i applikasjonssammenheng. Spring Framework vet ikke hvilken bønneavhengighet som skal kobles automatisk til hvilken referansevariabel. Løs dette problemet ved å legge til @Kvalifiserende kommentar til linje 7 og 10 i FieldQualifierAutowiredTest integrasjonstest:

@Autowired privat feltavhengighet feltavhengighet1; @Autowired private FieldDependency fieldDependency2;

slik at kodeblokken ser slik ut:

@Autowired @Qualifier ("autowiredFieldDependency") privat FieldDependency fieldDependency1; @Autowired @Qualifier ("anotherAutowiredFieldDependency") privat FieldDependency fieldDependency2;

Kjør testen igjen, og denne gangen vil den bestå.

4.1.3. Match etter navn

Det samme integrasjonstest-scenariet vil bli brukt til å demonstrere kjøringsbanen for samsvar etter navn når du bruker @Autowired kommentar for å injisere en feltavhengighet. Når autovirksomhet er avhengig av navn, @ComponentScan merknader må brukes med applikasjonssammenheng, ApplicationContextTestAutowiredName:

@Configuration @ComponentScan (basePackages = {"com.baeldung.dependency"}) offentlig klasse ApplicationContextTestAutowiredName {}

De @ComponentScan merknaden vil søke etter pakker for Java-klasser som er merket med @Komponent kommentar. For eksempel, i applikasjonssammenheng, com.baeldung. avhengighet pakken blir skannet for klasser som er merket med @Komponent kommentar. I dette scenariet må Spring Framework oppdage Vilkårlig avhengighet klasse, som har @Komponent kommentar:

@Component (value = "autowiredFieldDependency") offentlig klasse ArbitraryDependency {private final String label = "Arbitrary Dependency"; offentlig String toString () {returetikett; }}

Attributtverdien, autowiredFieldDependency, gått inn i @Komponent kommentar, forteller Spring Framework at Vilkårlig avhengighet klasse er en komponent som heter autowiredFieldDependency. For at @Autowired merknad for å løse avhengigheter etter navn, må komponentnavnet stemme overens med feltnavnet som er definert i FieldAutowiredNameTest integrasjonstest; se linje 8:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestAutowiredName.class) offentlig klasse FieldAutowiredNameIntegrationTest {@Autowired private ArbitraryDependency autowiredField @Test offentlig ugyldighet givenAutowiredAnnotation_WhenOnField_ThenDepValid () {assertNotNull (autowiredFieldDependency); assertEquals ("vilkårlig avhengighet", autowiredFieldDependency.toString ()); }}

Når FieldAutowiredNameTest integrasjonstest kjøres som den er, vil den bestå.

Men hvordan vet vi at @Autowired merknader påkalte virkelig kjøringsbanen for kamp-etter-navn? Endre navnet på referansevariabelen autowiredFieldDependency til et annet navn du ønsker, og kjør deretter testen igjen.

Denne gangen vil testen mislykkes og a NoUniqueBeanDefinitionException blir kastet. En lignende sjekk ville være å endre @Komponent attributtverdi, autowiredFieldDependency, til en annen verdi du ønsker, og kjør testen på nytt. EN NoUniqueBeanDefinitionException vil også bli kastet.

Dette unntaket er et bevis på at hvis det brukes feil bønnenavn, vil ingen gyldig bønne bli funnet. Derfor ble utførelsesstien match-by-name påkalt.

4.2. Setter Injection

Setterbasert injeksjon for @Autowired merknader er lik tilnærmingen demonstrert for @Ressurs setterbasert injeksjon. I stedet for å kommentere referansevariabelen med @Injiser kommentar, blir den tilsvarende setteren kommentert. Utførelsesbanene fulgt av feltbasert avhengighetsinjeksjon gjelder også for setterbasert injeksjon.

5. Bruke disse merknadene

Dette reiser spørsmålet om hvilken kommentar som skal brukes og under hvilke omstendigheter? Svaret på disse spørsmålene avhenger av designscenarioet for applikasjonen det gjelder, og hvordan utvikleren ønsker å utnytte polymorfisme basert på standardutførelsesbanene for hver kommentar.

5.1. Anvendelsesomfattende bruk av singler gjennom polymorfisme

Hvis utformingen er slik at applikasjonsatferd er basert på implementeringer av et grensesnitt eller en abstrakt klasse, og disse atferdene brukes i hele applikasjonen, så bruk enten @Injiser eller @Autowired kommentar.

Fordelen med denne tilnærmingen er at når applikasjonen oppgraderes, eller en oppdatering må brukes for å fikse en feil; så kan klasser byttes ut med minimal negativ innvirkning på den generelle applikasjonsatferden. I dette scenariet er den primære standardutførelsesbanen samsvarende etter type.

5.2. Finkornet applikasjonsatferdskonfigurasjon gjennom polymorfisme

Hvis designet er slik at applikasjonen har kompleks oppførsel, er hver atferd basert på forskjellige grensesnitt / abstrakte klasser, og bruken av hver av disse implementeringene varierer i applikasjonen, og bruk deretter @Ressurs kommentar. I dette scenariet er den primære standardutførelsesbanen match-by-name.

5.3. Avhengighetsinjeksjon bør håndteres utelukkende av Jakarta EE-plattformen

Hvis det er et designmandat for alle avhengigheter som skal injiseres av Jakarta EE-plattformen og ikke om våren, er valget mellom @Ressurs kommentar og @Injiser kommentar. Du bør begrense den endelige avgjørelsen mellom de to kommentarene, basert på hvilken standard kjøringsbane som kreves.

5.4. Avhengighetsinjeksjon bør håndteres utelukkende av vårrammen

Hvis mandatet er at alle avhengigheter skal håndteres av Spring Framework, er det eneste valget @Autowired kommentar.

5.5. Diskusjonsoppsummering

Tabellen nedenfor oppsummerer diskusjonen.

Scenario@Ressurs@Injiser@Autowired
Anvendelsesomfattende bruk av singletoner gjennom polymorfisme
Finkornet applikasjonsadferdskonfigurasjon gjennom polymorfisme
Avhengighetsinjeksjon skal håndteres utelukkende av Jakarta EE-plattformen
Avhengighetsinjeksjon skal håndteres utelukkende av Spring Framework

6. Konklusjon

Artikkelen hadde som mål å gi et dypere innblikk i oppførselen til hver kommentar. Å forstå hvordan hver kommentar oppfører seg, vil bidra til bedre generell applikasjonsdesign og vedlikehold.

Koden som ble brukt under diskusjonen finner du på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found