Guide till våren @Autowired

1. Översikt

Från och med våren 2.5 introducerade ramverket annoteringsdrivna beroendeinjektion . Huvudanteckningen för den här funktionen är @Autowired . Det gör att våren kan lösa och injicera samarbetsbönor i vår böna.

I denna handledning tar vi först en titt på hur du aktiverar autokoppling ocholikasätt att autowire bönor. Därefter pratar vi om att lösa bönakonflikter med @Qualifier- kommentar, samt potentiella undantagsscenarier.

2. Aktivera @Autowired Anteckningar

Spring-ramverket möjliggör automatisk insprutning av beroende. Med andra ord, genom att deklarera alla bönberoenden i en Spring-konfigurationsfil kan Spring-behållaren autowire relationer mellan samarbetsbönor . Detta kallas autobekoppling av vårbönor .

För att använda Java-baserad konfiguration i vår applikation, låt oss aktivera annoteringsdriven injektionför att ladda vår vårkonfiguration:

@Configuration @ComponentScan("com.baeldung.autowire.sample") public class AppConfig {}

Alternativt kan annotering används huvudsakligen för att aktivera beroenden för injektionsberoende i XML-filer på våren.

Dessutom introducerar Spring Boot @SpringBootApplication- anteckningen . Denna enskilda kommentar motsvarar att använda @Configuration , @EnableAutoConfiguration och @ComponentScan .

Låt oss använda den här kommentaren i applikationens huvudklass:

@SpringBootApplication class VehicleFactoryApplication { public static void main(String[] args) { SpringApplication.run(VehicleFactoryApplication.class, args); } }

Som ett resultat, när vi kör detta Spring Boot-program, kommer det automatiskt att skanna komponenterna i det aktuella paketet och dess underpaket . Således kommer den att registreras i vår applikationskontext och tillåta oss att injicera bönor med @Autowired .

3. Använda @Autowired

Efter att ha aktiverat annoteringsinjicering kan vi använda autokoppling på egenskaper, setter och konstruktörer .

3.1. @Autowired om egenskaper

Låt oss se hur vi kan kommentera en fastighet med @Autowired . Detta eliminerar behovet av getters och setters.

Låt oss först definiera en fooFormatter böna:

@Component("fooFormatter") public class FooFormatter { public String format() { return "foo"; } }

Sedan injicerar vi den här bönan i FooService- bönan med @Autowired i fältdefinitionen :

@Component public class FooService { @Autowired private FooFormatter fooFormatter; }

Som ett resultat injicerar Spring fooFormatter när FooService skapas.

3.2. @Autowired på Setters

Låt oss nu försöka lägga till @Autowired- kommentar på en setter-metod.

I följande exempel anropas settermetoden med förekomsten av FooFormatter när FooService skapas:

public class FooService { private FooFormatter fooFormatter; @Autowired public void setFooFormatter(FooFormatter fooFormatter) { this.fooFormatter = fooFormatter; } } 

3.3. @Autowired på konstruktörer

Slutligen, låt oss använda @Autowired på en konstruktör.

Vi ser att en instans av FooFormatter injiceras av Spring som ett argument till FooService- konstruktören:

public class FooService { private FooFormatter fooFormatter; @Autowired public FooService(FooFormatter fooFormatter) { this.fooFormatter = fooFormatter; } }

4. @Autowired och valfria beroenden

När en böna konstrueras ska @Autowired- beroenden vara tillgängliga. Annars, om våren inte kan lösa en böna för ledningar, kommer den att kasta ett undantag .

Följaktligen förhindrar det att Spring Containern startar framgångsrikt med undantag för formuläret:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.autowire.sample.FooDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

För att åtgärda detta måste vi deklarera en böna av önskad typ:

public class FooService { @Autowired(required = false) private FooDAO dataAccessor; }

5. Autowire Disambiguation

Som standard löser Spring @Autowired- poster efter typ. Om mer än en böna av samma typ finns i behållaren kommer ramverket att utgöra ett ödesdigert undantag .

För att lösa denna konflikt måste vi uttryckligen berätta för Spring vilken böna vi vill injicera.

5.1. Autokabel av @Qualifier

Låt oss till exempel se hur vi kan använda @Qualifier- anteckningen för att ange den önskade bönan.

Först definierar vi två bönor av typen Formatter :

@Component("fooFormatter") public class FooFormatter implements Formatter { public String format() { return "foo"; } }
@Component("barFormatter") public class BarFormatter implements Formatter { public String format() { return "bar"; } }

Låt oss nu försöka injicera en Formatter- böna i FooService- klassen:

public class FooService { @Autowired private Formatter formatter; }

I vårt exempel finns det två konkreta implementeringar av Formatter tillgängliga för vårcontainern . Som ett resultat kommer Spring att kasta ett NoUniqueBeanDefinitionException- undantag när du konstruerar FooService :

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.autowire.sample.Formatter] is defined: expected single matching bean but found 2: barFormatter,fooFormatter 

Vi kan undvika detta genom att begränsa implementeringen med en @Qualifier- kommentar:

public class FooService { @Autowired @Qualifier("fooFormatter") private Formatter formatter; }

När det finns flera bönor av samma typ är det en bra idé att använda @Qualifier för att undvika tvetydighet.

Observera att värdet på @Qualifier- anteckningen matchar det namn som deklareras i @Component- anteckningen för vårt implementering av FooFormatter .

5.2. Autokoppling med anpassad kvalificering

Våren låter oss också skapa vår egen @Qualifier- kommentar . För att göra det bör vi tillhandahålla @Qualifier- anteckningen med definitionen:

@Qualifier @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface FormatterType { String value(); }

Sedan kan vi använda FormatterType inom olika implementeringar för att ange ett anpassat värde:

@FormatterType("Foo") @Component public class FooFormatter implements Formatter { public String format() { return "foo"; } }
@FormatterType("Bar") @Component public class BarFormatter implements Formatter { public String format() { return "bar"; } }

Slutligen är vår anpassade kvalificeringsanmärkning redo att användas för autokoppling:

@Component public class FooService { @Autowired @FormatterType("Foo") private Formatter formatter; } 

Värdet som anges i @Target -metaanmärkningen begränsar var kvalificeringen ska tillämpas, vilket i vårt exempel är fält, metoder, typer och parametrar.

5.3. Autokabel efter namn

Spring använder bönans namn som standardvärde. Den kommer att inspektera behållaren och leta efter en böna med det exakta namnet som egenskap för att trådtråda den.

Därför, i vårt exempel, matchar Spring egendomens namn fooFormatter till FooFormatter- implementeringen. Därför injicerar den specifika implementeringen när du konstruerar FooService :

public class FooService { @Autowired private Formatter fooFormatter; }

6. Sammanfattning

I den här artikeln diskuterade vi autokoppling och olika sätt att använda den. Vi undersökte också sätt att lösa två vanliga undantag från autowiring orsakade av antingen en saknad böna eller en tvetydig böninjektion.

Källkoden för den här artikeln finns tillgänglig i GitHub-projektet.