Guía de Spring @Autowired

1. Información general

A partir de Spring 2.5, el marco introdujo la inyección de dependencia basada en anotaciones . La anotación principal de esta función es @Autowired . Permite que Spring resuelva e inyecte beans de colaboración en nuestro bean.

En este tutorial, primero veremos cómo habilitar el cableado automático y elvariosformas de autowire beans. Luego, hablaremos sobre la resolución de conflictos de beans utilizando la anotación @Qualifier , así como posibles escenarios de excepción.

2. Habilitación de anotaciones @Autowired

El marco de Spring permite la inyección automática de dependencias. En otras palabras, al declarar todas las dependencias de los beans en un archivo de configuración de Spring, el contenedor Spring puede conectar automáticamente las relaciones entre los beans que colaboran . Esto se llama cableado automático Spring Bean .

Para usar la configuración basada en Java en nuestra aplicación, habilitemos la inyección basada en anotacionespara cargar nuestra configuración de Spring:

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

Alternativamente, el La anotación se usa principalmente para activar las anotaciones de inyección de dependencia en archivos Spring XML.

Además, Spring Boot presenta la anotación @SpringBootApplication . Esta única anotación es equivalente a usar @Configuration , @EnableAutoConfiguration y @ComponentScan .

Usemos esta anotación en la clase principal de la aplicación:

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

Como resultado, cuando ejecutamos esta aplicación Spring Boot, escaneará automáticamente los componentes del paquete actual y sus subpaquetes . Por lo tanto, los registrará en el contexto de la aplicación de Spring y nos permitirá inyectar beans usando @Autowired .

3. Usando @Autowired

Después de habilitar la inyección de anotaciones, podemos usar el cableado automático en propiedades, establecedores y constructores .

3.1. @Autowired en propiedades

Veamos cómo podemos anotar una propiedad usando @Autowired . Esto elimina la necesidad de getters y setters.

Primero, definamos un bean fooFormatter :

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

A continuación, vamos a inyectar este frijol en el FooService bean mediante @Autowired en la definición de campo:

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

Como resultado, Spring inyecta fooFormatter cuando se crea FooService .

3.2. @Autowired en Setters

Ahora intentemos agregar la anotación @Autowired en un método de establecimiento.

En el siguiente ejemplo, se llama al método setter con la instancia de FooFormatter cuando se crea FooService :

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

3.3. @Autowired en constructores

Finalmente, usemos @Autowired en un constructor.

Veremos que Spring inyecta una instancia de FooFormatter como argumento para el constructor FooService :

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

4. Dependencias @Autowired y opcionales

Cuando se está construyendo un bean, las dependencias @Autowired deberían estar disponibles. De lo contrario, si Spring no puede resolver un bean para el cableado, lanzará una excepción .

En consecuencia, evita que el contenedor Spring se inicie con éxito con una excepción del formulario:

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

Para solucionar esto, necesitamos declarar un bean del tipo requerido:

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

5. Desambiguación de cableado automático

De forma predeterminada, Spring resuelve las entradas @Autowired por tipo. Si más de un bean del mismo tipo está disponible en el contenedor, el marco lanzará una excepción fatal .

Para resolver este conflicto, necesitamos decirle a Spring explícitamente qué bean queremos inyectar.

5.1. Autowiring por @Qualifier

Por ejemplo, veamos cómo podemos usar la anotación @Qualifier para indicar el bean requerido.

Primero, definiremos 2 beans de tipo 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"; } }

Ahora intentemos inyectar un bean Formatter en la clase FooService :

public class FooService { @Autowired private Formatter formatter; }

En nuestro ejemplo, hay dos implementaciones concretas de Formatter disponibles para el contenedor Spring. Como resultado, Spring lanzará una excepción NoUniqueBeanDefinitionException al construir 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 

Podemos evitar esto acotando la implementación usando una anotación @Qualifier :

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

Cuando hay varios beans del mismo tipo, es una buena idea usar @Qualifier para evitar ambigüedades.

Tenga en cuenta que el valor de la anotación @Qualifier coincide con el nombre declarado en la anotación @Component de nuestra implementación FooFormatter .

5.2. Cableado automático por calificador personalizado

Spring también nos permite crear nuestra propia anotación @Qualifier personalizada . Para hacerlo, debemos proporcionar la anotación @Qualifier con la definición:

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

Luego podemos usar FormatterType dentro de varias implementaciones para especificar un valor personalizado:

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

Finalmente, nuestra anotación de calificador personalizada está lista para usar para el cableado automático:

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

El valor especificado en la meta-anotación @Target restringe dónde aplicar el calificador, que en nuestro ejemplo son campos, métodos, tipos y parámetros.

5.3. Cableado automático por nombre

Spring usa el nombre del bean como valor calificador predeterminado. Inspeccionará el contenedor y buscará un bean con el nombre exacto como propiedad para autowire.

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.