Ledningsføring i foråret: @Autowired, @Resource og @Inject

1. Oversigt

Denne forårsrammeartikel vil demonstrere brugen af ​​annoteringer relateret til afhængighedsinjektion, nemlig @Ressource, @Indsprøjteog @Autowired kommentarer. Disse kommentarer giver klasser en deklarativ måde at løse afhængigheder på. For eksempel:

@Autowired ArbitraryClass arbObject;

i modsætning til at instantiere dem direkte (den tvingende måde), for eksempel:

ArbitraryClass arbObject = ny ArbitraryClass ();

To af de tre annoteringer hører til Java-udvidelsespakken: javax.annotation.Ressource og javax.inject.Inject. Det @Autowired kommentar hører til org.springframework.beans.factory.annotation pakke.

Hver af disse kommentarer kan løse afhængigheder enten ved feltinjektion eller ved setterinjektion. Et forenklet, men praktisk eksempel vil blive brugt til at demonstrere sondringen mellem de tre kommentarer, baseret på de eksekveringsstier, som hver annotering tager.

Eksemplerne vil fokusere på, hvordan man bruger de tre injektionsanmærkninger under integrationstest. Den afhængighed, der kræves af testen, kan enten være en vilkårlig fil eller en vilkårlig klasse.

2. Den @Ressource ENnotation

Det @Ressource annotation er en del af JSR-250-annotationssamlingen og er pakket med Jakarta EE. Denne kommentar har følgende eksekveringsstier, der er angivet med forrang:

  1. Match efter navn
  2. Match efter type
  3. Match efter kvalifikator

Disse udførelsesstier gælder for både setter og feltinjektion.

2.1. Feltinjektion

Løsning af afhængigheder ved feltinjektion opnås ved at kommentere en instansvariabel med @Ressource kommentar.

2.1.1. Match efter navn

Integrationstesten, der bruges til at demonstrere match-by-name-feltinjektion, er angivet som følger:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestResourceNameType.class) public class FieldResourceInjectionIntegrationTest {@Resource (name = "namedFile") privat standardFil @Test offentlig ugyldighed givenResourceAnnotation_WhenOnField_ThenDependencyValid () {assertNotNull (defaultFile); assertEquals ("namedFile.txt", defaultFile.getName ()); }}

Lad os gennemgå koden. I FieldResourceInjectionTest integrationstest, ved linje 7 opnås opløsningen af ​​afhængighed ved navn ved at overføre bønnenavnet som en attributværdi til @Ressource kommentar:

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

Denne konfiguration løser afhængigheder ved hjælp af stien til udførelse af match efter navn. Bønnen navngivet fil skal defineres i ApplicationContextTestResourceNameType applikationskontekst.

Bemærk, at bønne-id'et og den tilsvarende referenceattributværdi skal matche:

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

Manglende definition af bønnen i applikationens sammenhæng vil resultere i a org.springframework.beans.factory.NoSuchBeanDefinitionException bliver kastet. Dette kan demonstreres ved at ændre attributværdien, der overføres til @Bønne kommentar, i ApplicationContextTestResourceNameType applikationskontekst eller ændre den attributværdi, der sendes til @Ressource kommentar, i FieldResourceInjectionTest integrationstest.

2.1.2. Match efter type

For at demonstrere match-for-type-eksekveringsstien skal du bare fjerne attributværdien på linje 7 i FieldResourceInjectionTest integrationstest, så det ser ud som følger:

@Resource privat fil defaultFile;

og kør testen igen.

Testen vil stadig bestå, for hvis @Ressource kommentar modtager ikke et bønnenavn som attributværdi, Spring Framework fortsætter med det næste niveau af forrang, match-for-type, for at prøve at løse afhængigheden.

2.1.3. Match efter kvalifikator

For at demonstrere match-by-qualifier-eksekveringsstien ændres integrationstest-scenariet, så der er to bønner defineret i ApplicationContextTestResourceQualifier applikationskontekst:

@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"); returneret navngivet fil; }}

Det QualifierResourceInjectionTest integrationstest vil blive brugt til at demonstrere afhængighed af afhængighed-for-kvalifikationsopløsning. I dette scenarie skal en bestemt bønneafhængighed injiceres i hver referencevariabel:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestResourceQualifier.class) offentlig klasse QualifierResourceInjectionIntegrationTest {@Resource privat filafhængighed1; @Resource private Filafhængighed2; @Test offentlig ugyldighed givenResourceAnnotation_WhenField_ThenDependency1Valid () {assertNotNull (afhængighed1); assertEquals ("defaultFile.txt", dependency1.getName ()); } @Test offentlig ugyldighed givenResourceQualifier_WhenField_ThenDependency2Valid () {assertNotNull (dependency2); assertEquals ("namedFile.txt", dependency2.getName ()); }}

Kør integrationstesten og en org.springframework.beans.factory.NoUniqueBeanDefinitionException kastes. Denne undtagelse kastes, fordi applikationskonteksten har fundet to definitioner af bønner af typen Fil, og det er forvirret, hvilken bønne der skal løse afhængigheden.

For at løse dette problem henvises til linje 7 til linje 10 i QualifierResourceInjectionTest integrationstest:

@Resource private Filafhængighed1; @Resource private Filafhængighed2;

og tilføj følgende linjer kode:

@Qualifier ("standardfil") @Qualifier ("navngivet fil")

så kodeblokken ser således ud:

@Resource @Qualifier ("defaultFile") privat filafhængighed1; @Resource @Qualifier ("namedFile") privat filafhængighed2;

Kør integrationstesten igen, denne gang skal den bestå. Formålet med denne test var at demonstrere, at selvom der er defineret flere bønner i en applikationskontekst, er @Kvalifikator annotering rydder enhver forvirring ved at tillade, at specifikke afhængigheder injiceres i en klasse.

2.2. Setter Injection

Eksekveringsstier, der tages, når der indsprøjtes afhængigheder på et felt, gælder for setterbaseret injektion.

2.2.1. Match efter navn

Den eneste forskel er MethodResourceInjectionTest integration test har en setter metode:

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

Løsning af afhængigheder ved setterinjektion sker ved at kommentere en referencevariabels tilsvarende settermetode. Giv navnet på bønneafhængigheden som en attributværdi til @Ressource kommentar:

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

Det navngivet fil bønneafhængighed vil blive genbrugt i dette eksempel. Bønnenavnet og den tilsvarende attributværdi skal matche.

Kør integrationstesten som den er, og den vil bestå.

For at se, at afhængigheden faktisk blev løst af stien match-by-name, skal du ændre attributværdien, der er sendt til @Ressource kommentar til en værdi efter eget valg, og kør testen igen. Denne gang mislykkes testen med en NoSuchBeanDefinitionException.

2.2.2. Match efter type

For at demonstrere setterbaseret, match-by-type-udførelse bruger vi MethodByTypeResourceTest integrationstest:

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

Kør denne test som den er, og den vil bestå.

For at kontrollere, at Fil afhængighed blev faktisk løst af match-for-type-eksekveringsstien, skift klassetypen for defaultFile variabel til en anden klassetype som Snor. Udfør MethodByTypeResourceTest integrationstest igen og denne gang a NoSuchBeanDefinitionException vil blive kastet.

Undtagelsen bekræfter, at match-by-type faktisk blev brugt til at løse Fil afhængighed. Det NoSuchBeanDefinitionException bekræfter, at referencevariabelnavnet ikke behøver at matche bønnenavnet. I stedet afhænger afhængighedsopløsningen af, at bønnens klassetype svarer til referencevariabelens klassetype.

2.2.3. Match efter kvalifikator

Det MethodByQualifierResourceTest integrationstest vil blive brugt til at demonstrere stien match-by-qualifier:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestResourceQualifier.class) public class MethodByQualifierResourceIntegrationTest {private File arbDependency; privat fil en andenArbDependency; @Test offentlig ugyldighed givenResourceQualifier_WhenSetter_ThenValidDependencies () {assertNotNull (arbDependency); assertEquals ("namedFile.txt", arbDependency.getName ()); assertNotNull (anotherArbDependency); assertEquals ("defaultFile.txt", anotherArbDependency.getName ()); } @Resource @Qualifier ("namedFile") offentlig ugyldighed setArbDependency (File arbDependency) {this.arbDependency = arbDependency; } @Resource @Qualifier ("defaultFile") offentlig ugyldighed setAnotherArbDependency (File anotherArbDependency) {this.anotherArbDependency = anotherArbDependency; }}

Formålet med denne test er at demonstrere, at selvom flere bønnerimplementeringer af en bestemt type er defineret i en applikationskontekst, a @Kvalifikator kommentar kan bruges sammen med @Ressource kommentar for at løse en afhængighed.

Svarende til feltbaseret afhængighedsinjektion, hvis der er defineret flere bønner i en applikationskontekst, a NoUniqueBeanDefinitionException kastes, hvis nej @Kvalifikator annotering bruges til at specificere, hvilken bønne der skal bruges til at løse afhængigheder.

3. Den @Indsprøjte Kommentar

Det @Indsprøjte annotation hører til JSR-330-annotationssamlingen. Denne kommentar har følgende eksekveringsstier, angivet med forrang:

  1. Match efter type
  2. Match efter kvalifikator
  3. Match efter navn

Disse udførelsesstier gælder for både setter og feltinjektion. For at få adgang til @Indsprøjte kommentar, den javax.inject biblioteket skal erklæres som en Gradle eller Maven afhængighed.

For Gradle:

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

For Maven:

 javax.inject javax.inject 1 

3.1. Feltinjektion

3.1.1. Match efter type

Eksempel på integrationstest vil blive ændret til at bruge en anden type afhængighed, nemlig Vilkårlig afhængighed klasse. Det Vilkårlig afhængighed klasseafhængighed tjener kun som en simpel afhængighed og har ingen yderligere betydning. Det er angivet som følger:

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

Det FieldInjectTest den pågældende integrationstest er angivet som følger:

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

I modsætning til @Ressource kommentar, der løser afhængigheder ved navn først; standardadfærden for @Indsprøjte annotering løser afhængigheder efter type.

Dette betyder, at selvom et klassereferencevariabelnavn adskiller sig fra bønnenavnet, vil afhængigheden stadig blive løst, forudsat at bønnen er defineret i applikationskonteksten. Bemærk hvordan referencevariabelnavnet i følgende test:

@Inject private ArbitraryDependency fieldInjectDependency;

adskiller sig fra bønnenavnet, der er konfigureret i applikationskonteksten:

@Bean public ArbitraryDependency injectDependency () {ArbitraryDependency injectDependency = new ArbitraryDependency (); returindsprøjtning Afhængighed; }

og når testen udføres, er den i stand til at løse afhængigheden.

3.1.2. Match efter kvalifikator

Men hvad hvis der er flere implementeringer af en bestemt klassetype, og en bestemt klasse kræver en bestemt bønne? Lad os ændre eksemplet på integrationstest, så der kræves en anden afhængighed.

I dette eksempel underklasserer vi Vilkårlig afhængighed klasse, der bruges i eksemplet match-by-type, til at oprette En anden vilkårlig afhængighed klasse:

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

Målet med hver testtilfælde er at sikre, at hver afhængighed indsprøjtes korrekt i hver referencevariabel:

@Inject private ArbitraryDependency defaultDependency; @Injicér privat vilkårlig afhængighed navngivet afhængighed;

Det FieldQualifierInjectTest integrationstest, der bruges til at demonstrere match efter kvalifikator, er vist som følger:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestInjectQualifier.class) offentlig klasse FieldQualifierInjectIntegrationTest {@Inject private ArbitraryDependency defaultDependency; @Injicér privat vilkårlig afhængighed navngivet afhængighed; @Test offentlig ugyldighed givenInjectQualifier_WhenOnField_ThenDefaultFileValid () {assertNotNull (standardafhængighed); assertEquals ("vilkårlig afhængighed", defaultDependency.toString ()); } @Test offentlig ugyldighed givenInjectQualifier_WhenOnField_ThenNamedFileValid () {assertNotNull (standardafhængighed); assertEquals ("En anden vilkårlig afhængighed", navngivetDependency.toString ()); }}

Hvis der er flere implementeringer af en bestemt klasse i en applikationskontekst og FieldQualifierInjectTest integrationstest forsøger at indsprøjte afhængighederne på nedenstående måde:

@Inject private ArbitraryDependency defaultDependency; @Injicér privat vilkårlig afhængighed navngivet afhængighed;

-en NoUniqueBeanDefinitionException vil blive kastet.

At kaste denne undtagelse er Spring Framework's måde at påpege, at der er flere implementeringer af en bestemt klasse, og det er forvirret over, hvilken man skal bruge. For at belyse forvirringen skal du gå til linje 7 og 10 i FieldQualifierInjectTest integrationstest:

@Inject private ArbitraryDependency defaultDependency; @Injicér privat vilkårlig afhængighed navngivet afhængighed;

videregive det krævede bønnenavn til @Kvalifikator kommentar, som bruges sammen med @Indsprøjte kommentar. Kodeblokken ser nu ud som følger:

@Inject @Qualifier ("defaultFile") privat ArbitraryDependency defaultDependency; @Inject @Qualifier ("namedFile") privat vilkårlig afhængighed navngivet afhængighed;

Det @Kvalifikator kommentar forventer en streng matchning, når man modtager et bønnenavn. Sørg for, at bønnenavnet sendes til Kvalifikator korrekt, ellers a NoUniqueBeanDefinitionException vil blive kastet. Kør testen igen, og denne gang skal den bestå.

3.1.3. Match efter navn

Det FieldByNameInjectTest integrationstest, der bruges til at demonstrere match ved navn, svarer til stien match for type-udførelse. Den eneste forskel er nu, at der kræves en bestemt bønne i modsætning til en bestemt type. I dette eksempel underklasserer vi Vilkårlig afhængighed klasse igen for at producere Endnu en anden vilkårlig afhængighed klasse:

offentlig klasse YetAnotherArbitraryDependency udvider ArbitraryDependency {private final String label = "Endnu en anden vilkårlig afhængighed"; offentlig String toString () {returetiket; }}

For at demonstrere stien match-by-name-eksekvering bruger vi følgende integrationstest:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestInjectName.class) public class FieldByNameInjectIntegrationTest {@Inject @Named ("yetAnotherFieldInjectDependency) @Test offentlig ugyldighed givenInjectQualifier_WhenSetOnField_ThenDependencyValid () {assertNotNull (yetAnotherFieldInjectDependency); assertEquals ("Endnu en vilkårlig afhængighed", yetAnotherFieldInjectDependency.toString ()); }}

Ansøgningskonteksten er angivet som følger:

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

Kør integrationstesten som den er, og den vil bestå.

For at kontrollere, at afhængigheden faktisk blev injiceret af match-by-name-eksekveringsstien, skal du ændre værdien, yetAnotherFieldInjectDependency, der blev sendt videre til @Som hedder kommentar til et andet navn efter eget valg. Kør testen igen - denne gang, a NoSuchBeanDefinitionException kastes.

3.2. Setter Injection

Setterbaseret injektion til @Indsprøjte kommentar svarer til den metode, der anvendes til @Ressource setter-baseret injektion. I stedet for at kommentere referencevariablen kommenteres den tilsvarende settermetode. Eksekveringsstier fulgt af feltbaseret afhængighedsinjektion gælder også for setterbaseret injektion.

4. Den @Autowired Kommentar

Opførelsen af @Autowired kommentar svarer til @Indsprøjte kommentar. Den eneste forskel er, at @Autowired kommentar er en del af forårets ramme. Denne kommentar har de samme udførelsesstier som @Indsprøjte annotering, opført i rækkefølge:

  1. Match efter type
  2. Match efter kvalifikator
  3. Match efter navn

Disse udførelsesstier gælder for både setter og feltinjektion.

4.1. Feltinjektion

4.1.1. Match efter type

Eksemplet på integrationstest bruges til at demonstrere @Autowired match-by-type-eksekveringssti vil svare til testen, der bruges til at demonstrere @Indsprøjte match-for-type udførelsessti. Det FieldAutowiredTest integrationstest, der bruges til at demonstrere match-for-type ved hjælp af @Autowired kommentar er angivet som følger:

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

Applikationskonteksten til denne integrationstest er angivet som følger:

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

Målet med integrationstesten er at demonstrere, at match-by-type har forrang for de andre eksekveringsstier. Bemærk på linje 8 i FieldAutowiredTest integrationstest hvordan referencevariabelnavnet:

@Autowired privat ArbitraryDependency fieldDependency;

er forskellig fra bønnenavnet i applikationskonteksten:

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

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

For at bekræfte, at afhængigheden faktisk blev løst ved hjælp af stien match-by-type, skal du ændre typen af feltafhængighed referencevariabel og kør integrationstesten igen. Denne gang runde FieldAutowiredTest integrationstest skal mislykkes med en NoSuchBeanDefinitionException bliver kastet. Dette bekræfter, at match-by-type blev brugt til at løse afhængigheden.

4.1.2. Match efter kvalifikator

Hvad hvis vi står over for en situation, hvor flere bønnerimplementeringer er defineret i applikationskonteksten, som den, der er anført nedenfor:

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

Hvis den FieldQualifierAutowiredTest integrationstest, der er anført nedenfor, udføres:

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

-en NoUniqueBeanDefinitionException vil blive kastet.

Undtagelsen skyldes den tvetydighed, der er forårsaget af de to bønner, der er defineret i applikationskonteksten. Spring Framework ved ikke, hvilken bønneafhængighed der skal autowired til hvilken referencevariabel. Løs dette problem ved at tilføje @Kvalifikator kommentar til linje 7 og 10 i FieldQualifierAutowiredTest integrationstest:

@Autowired privat FieldDependency fieldDependency1; @Autowired privat FieldDependency fieldDependency2;

så kodeblokken ser således ud:

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

Kør testen igen, og denne gang vil den bestå.

4.1.3. Match efter navn

Det samme integrationstestscenarie vil blive brugt til at demonstrere stien til udførelse af match-by-navn, når du bruger @Autowired kommentar for at indsprøjte en feltafhængighed. Når autokabler afhængigheder efter navn, @ComponentScan kommentar skal bruges sammen med applikationens sammenhæng, ApplicationContextTestAutowiredName:

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

Det @ComponentScan annotation søger i pakker til Java-klasser, der er kommenteret med @Komponent kommentar. For eksempel i applikationskonteksten com.baeldung.dependency pakken scannes for klasser, der er kommenteret med @Komponent kommentar. I dette scenario skal Spring Framework registrere Vilkårlig afhængighed klasse, som har @Komponent kommentar:

@Komponent (værdi = "autowiredFieldDependency") offentlig klasse ArbitraryDependency {private final String label = "Arbitrary Dependency"; offentlig String toString () {returetiket; }}

Attributværdien, autowiredFieldDependency, overført til @Komponent kommentar, fortæller Spring Framework, at Vilkårlig afhængighed klasse er en komponent med navnet autowiredFieldDependency. For at @Autowired kommentar for at løse afhængigheder efter navn, skal komponentnavnet svare til det feltnavn, der er defineret i FieldAutowiredNameTest integration test; se linie 8:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (loader = AnnotationConfigContextLoader.class, classes = ApplicationContextTestAutowiredName.class) public class FieldAutowiredNameIntegrationTest {@Autowired private ArbitraryDependency autowiredFieldDependent @Test offentlig ugyldighed givenAutowiredAnnotation_WhenOnField_ThenDepValid () {assertNotNull (autowiredFieldDependency); assertEquals ("vilkårlig afhængighed", autowiredFieldDependency.toString ()); }}

Når FieldAutowiredNameTest integrationstest køres som den er, den vil bestå.

Men hvordan ved vi, at @Autowired annotation påkaldte virkelig stien match-by-name eksekvering? Skift navnet på referencevariablen autowiredFieldDependency til et andet navn efter eget valg, og kør derefter testen igen.

Denne gang mislykkes testen, og a NoUniqueBeanDefinitionException kastes. En lignende kontrol ville være at ændre @Komponent attributværdi, autowiredFieldDependency, til en anden værdi efter eget valg, og kør testen igen. EN NoUniqueBeanDefinitionException vil også blive kastet.

Denne undtagelse er bevis for, at hvis der anvendes et forkert bønnenavn, vil der ikke blive fundet nogen gyldig bønne. Derfor blev sti til udførelse af match-by-navn påberåbt.

4.2. Setter Injection

Setterbaseret injektion til @Autowired kommentar er den samme metode, der er vist for @Ressource setterbaseret injektion. I stedet for at kommentere referencevariablen med @Indsprøjte kommentar, den tilsvarende setter kommenteres. Eksekveringsstier fulgt af feltbaseret afhængighedsinjektion gælder også for setterbaseret injektion.

5. Anvendelse af disse bemærkninger

Dette rejser spørgsmålet, hvilken kommentar skal bruges, og under hvilke omstændigheder? Svaret på disse spørgsmål afhænger af designscenariet, som den pågældende applikation står over for, og hvordan udvikleren ønsker at udnytte polymorfisme baseret på standardudførelsesstierne for hver kommentar.

5.1. Anvendelsesbred brug af singletoner gennem polymorfisme

Hvis designet er sådan, at applikationsadfærd er baseret på implementeringer af en grænseflade eller en abstrakt klasse, og denne adfærd bruges i hele applikationen, skal du enten bruge @Indsprøjte eller @Autowired kommentar.

Fordelen ved denne tilgang er, at når applikationen opgraderes, eller der skal anvendes en patch for at rette en fejl; så kan klasser byttes ud med minimal negativ indvirkning på den samlede applikationsadfærd. I dette scenarie er den primære standardudførelsessti match-for-type.

5.2. Finkornet applikationsadfærdskonfiguration gennem polymorfisme

Hvis designet er sådan, at applikationen har kompleks adfærd, er hver adfærd baseret på forskellige grænseflader / abstrakte klasser, og brugen af ​​hver af disse implementeringer varierer på tværs af applikationen, og brug derefter @Ressource kommentar. I dette scenarie er den primære standardudførelsessti match-by-name.

5.3. Afhængighedsinjektion bør håndteres udelukkende af Jakarta EE-platformen

Hvis der er et designmandat for alle afhængigheder, der skal injiceres af Jakarta EE-platformen og ikke foråret, er valget mellem @Ressource kommentar og @Indsprøjte kommentar. Du bør indsnævre den endelige beslutning mellem de to kommentarer, baseret på hvilken standardudførelsessti der kræves.

5.4. Afhængighedsinjektion bør håndteres udelukkende af foråret

Hvis mandatet er, at alle afhængigheder håndteres af Spring Framework, er det eneste valg det @Autowired kommentar.

5.5. Diskussionsoversigt

Tabellen nedenfor opsummerer diskussionen.

Scenarie@Ressource@Indsprøjte@Autowired
Anvendelsesomfattende brug af singletoner gennem polymorfisme
Finkornet applikationsadfærdskonfiguration gennem polymorfisme
Afhængighedsindsprøjtning skal håndteres udelukkende af Jakarta EE-platformen
Afhængighedsindsprøjtning skal udelukkende håndteres af Spring Framework

6. Konklusion

Artiklen havde til formål at give en dybere indsigt i opførelsen af ​​hver kommentar. At forstå, hvordan hver annotering opfører sig, vil bidrage til bedre overordnet applikationsdesign og vedligeholdelse.

Koden, der blev brugt under diskussionen, kan findes på GitHub.