Ghid pentru Spring @Autowired

1. Prezentare generală

Începând cu primăvara 2.5, cadrul a introdus injecția de dependență bazată pe adnotări . Adnotarea principală a acestei caracteristici este @Autowired . Permite Spring să rezolve și să injecteze fasole colaboratoare în fasole.

În acest tutorial, vom arunca mai întâi cum să activați cablarea automată șivariatmodalități de a semnaliza automat fasolea. Ulterior, vom vorbi despre rezolvarea conflictelor de fasole folosind adnotarea @Qualifier , precum și despre potențialele scenarii de excepție.

2. Activarea adnotărilor @Autowired

Cadrul Spring permite injectarea automată a dependenței. Cu alte cuvinte, declarând toate dependențele de fasole într-un fișier de configurare Spring, containerul Spring poate conecta în mod automat relații între fasole de colaborare . Aceasta se numește cablare automată Spring Bean .

Pentru a utiliza configurația bazată pe Java în aplicația noastră, să activăm injecția bazată pe adnotăripentru a încărca configurația noastră de primăvară:

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

Alternativ, adnotarea este utilizată în principal pentru a activa adnotările de injecție de dependență în fișierele XML Spring.

Mai mult, Spring Boot introduce adnotarea @SpringBootApplication . Această adnotare unică este echivalentă cu utilizarea @Configuration , @EnableAutoConfiguration și @ComponentScan .

Să folosim această adnotare în clasa principală a aplicației:

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

Ca urmare, atunci când rulăm această aplicație Spring Boot, aceasta va scana automat componentele din pachetul curent și subpachetele sale . Astfel, le va înregistra în contextul aplicației de primăvară și ne va permite să injectăm fasole folosind @Autowired .

3. Folosind @Autowired

După activarea injecției de adnotări, putem folosi cablarea automată pe proprietăți, setere și constructori .

3.1. @Autowired pe proprietăți

Să vedem cum putem adnota o proprietate folosind @Autowired . Acest lucru elimină nevoia de getters și seteri.

Mai întâi, să definim un bob de fooFormatter :

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

Apoi, vom injecta acest bean în beanul FooService folosind @Autowired în definiția câmpului:

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

Ca urmare, Spring injectează fooFormatter atunci când este creat FooService .

3.2. @Autowired pe Seters

Acum, să încercăm să adăugăm adnotare @Autowired pe o metodă de setare .

În exemplul următor, metoda setter este apelată cu instanța FooFormatter atunci când este creat FooService :

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

3.3. @Autowired pe constructori

În cele din urmă, să folosim @Autowired pe un constructor.

Vom vedea că o instanță de FooFormatter este injectată de Spring ca argument pentru constructorul FooService :

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

4. @Autowired și dependențe opționale

Când se construiește un bob, ar trebui să fie disponibile dependențele @Autowired . În caz contrar, dacă Spring nu poate rezolva o bobină pentru cablare, va produce o excepție .

În consecință, împiedică lansarea cu succes a containerului Spring, cu o excepție a formularului:

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)}

Pentru a remedia acest lucru, trebuie să declarăm un bob de tipul necesar:

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

5. Dezambiguizarea Autowire

În mod implicit, Spring rezolvă intrările @Autowired după tip. Dacă mai mult de un bob de același tip este disponibil în container, cadrul va arunca o excepție fatală .

Pentru a rezolva acest conflict, trebuie să-i spunem în mod explicit lui Spring ce boabă vrem să injectăm.

5.1. Cablare automată de @Qualifier

De exemplu, să vedem cum putem folosi adnotarea @Qualifier pentru a indica bobul necesar.

Mai întâi, vom defini 2 fasole de tip 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"; } }

Acum, să încercăm să injectăm un bob Formatter în clasa FooService :

public class FooService { @Autowired private Formatter formatter; }

În exemplul nostru, există două implementări concrete de Formatter disponibile pentru containerul Spring. Ca rezultat, Spring va arunca o excepție NoUniqueBeanDefinitionException atunci când construiește 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 

Putem evita acest lucru restrângând implementarea utilizând o adnotare @Qualifier :

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

Când există mai multe fasole de același tip, este o idee bună să utilizați @Qualifier pentru a evita ambiguitatea.

Vă rugăm să rețineți că valoarea @Qualifier meciurilor de adnotare cu numele declarată în @Component adnotarea noastre FooFormatter implementare.

5.2. Cablare automată prin calificator personalizat

Primăvara ne permite, de asemenea, să creăm propria noastră adnotare personalizată @Qualifier . Pentru a face acest lucru, ar trebui să furnizăm adnotarea @Qualifier cu definiția:

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

Apoi putem folosi FormatterType în cadrul diferitelor implementări pentru a specifica o valoare personalizată:

@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"; } }

În cele din urmă, adnotarea noastră personalizată Calificator este gata de utilizare pentru cablarea automată:

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

Valoarea specificată în meta-adnotarea @Target restricționează unde se aplică calificativul, care în exemplul nostru este câmpuri, metode, tipuri și parametri.

5.3. Cablare automată după nume

Spring utilizează numele beanului ca valoare implicită a calificativului. Acesta va inspecta recipientul și va căuta un bob cu numele exact ca proprietate pentru a-l conecta automat.

Hence, in our example, Spring matches the fooFormatter property name to the FooFormatter implementation. Therefore, it injects that specific implementation when constructing FooService:

public class FooService { @Autowired private Formatter fooFormatter; }

6. Conclusion

In this article, we discussed autowiring and the different ways to use it. We also examined ways to solve two common autowiring exceptions caused by either a missing bean or an ambiguous bean injection.

The source code of this article is available on the GitHub project.