Using Autowired
Uso de @Autowired
La anotación @Inject de JSR-330 puede utilizarse en lugar de la anotación @Autowired de Spring en los ejemplos de esta sección. Consulta la documentación sobre anotaciones estándar JSR-330 para obtener más información.
Puedes aplicar la anotación @Autowired a constructores, como muestra el siguiente ejemplo:
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
No es necesario anotar con @Autowired ese constructor si el bean de destino define un único constructor. Sin embargo, si hay varios constructores disponibles y no existe un constructor principal o predeterminado, al menos uno debe anotarse con @Autowired para indicar al contenedor cuál debe utilizar. Consulta la sección sobre resolución de constructores para más información.
Puedes aplicar @Autowired a métodos setter tradicionales:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
También puedes aplicar @Autowired a métodos con nombres arbitrarios y varios argumentos:
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
También puedes aplicar @Autowired a campos e incluso combinarlo con constructores:
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
private MovieCatalog movieCatalog;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
Asegúrate de que los componentes de destino —por ejemplo, MovieCatalog o CustomerPreferenceDao— se declaren de forma coherente con el tipo que utilizas en los puntos de inyección anotados con @Autowired. De lo contrario, la inyección puede fallar en tiempo de ejecución con un error de que no se ha encontrado ningún tipo coincidente.
Para beans definidos mediante XML o clases de componentes encontradas mediante exploración del classpath, el contenedor suele conocer de antemano el tipo concreto. Sin embargo, en métodos de fábrica @Bean, debes asegurarte de que el tipo de retorno declarado sea suficientemente expresivo.
Para componentes que implementan varias interfaces o que pueden ser referenciados por su tipo de implementación, declara el tipo de retorno más específico en el método de fábrica, al menos tan específico como requieran los puntos de inyección que hacen referencia al bean.
Autoinyección
@Autowired también considera las autorreferencias para la inyección, es decir, referencias al bean que se está inyectando en ese momento.
Sin embargo, la autoinyección es un mecanismo de reserva. Las dependencias normales de otros componentes siempre tienen prioridad. Por tanto, las autorreferencias no participan en la selección habitual de candidatos de autoconexión y, en particular, nunca son candidatas principales. Al contrario, siempre tienen la prioridad más baja.
En la práctica, debes utilizar las autorreferencias solo como último recurso, por ejemplo, para invocar otros métodos de la misma instancia a través del proxy transaccional del bean. Como alternativa, considera extraer los métodos afectados a un bean delegado independiente.
Otra alternativa consiste en utilizar @Resource, que puede obtener un proxy del bean actual mediante su nombre único.
Intentar inyectar los resultados de métodos @Bean de la misma clase @Configuration también es, en la práctica, un escenario de autorreferencia. Resuelve esas referencias de forma diferida en la firma del método donde realmente se necesitan —en lugar de mediante un campo autoconectado de la clase de configuración— o declara los métodos @Bean afectados como static, separándolos de la instancia de la clase de configuración que los contiene y de su ciclo de vida.
En caso contrario, esos beans solo se consideran en la fase de reserva, y se seleccionan en su lugar como candidatos principales los beans coincidentes de otras clases de configuración, cuando estén disponibles.
Arrays, colecciones y mapas
Puedes indicar a Spring que proporcione todos los beans de un tipo concreto del ApplicationContext aplicando @Autowired a un campo o método que espere un array de ese tipo:
public class MovieRecommender {
@Autowired
private MovieCatalog[] movieCatalogs;
// ...
}
Lo mismo se aplica a las colecciones tipadas:
public class MovieRecommender {
private Set<MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
}
Los beans de destino pueden implementar la interfaz org.springframework.core.Ordered o utilizar la anotación @Order o la anotación estándar @Priority si quieres ordenar los elementos del array o de la lista de una manera específica. En caso contrario, el orden sigue el orden de registro de las definiciones de bean de destino correspondientes en el contenedor.
Puedes declarar @Order en la clase de destino y en métodos @Bean, incluso para definiciones de bean individuales cuando varias definiciones utilizan la misma clase de bean. Los valores de @Order pueden influir en las prioridades de los puntos de inyección, pero no influyen en el orden de inicio de los singletons, que es una cuestión independiente determinada por las relaciones de dependencia y las declaraciones @DependsOn.
Las anotaciones @Order en clases de configuración solo influyen en el orden de evaluación dentro del conjunto general de clases de configuración durante el inicio. Estos valores de orden a nivel de configuración no afectan en absoluto a los métodos @Bean que contienen.
Para el orden a nivel de bean, cada método @Bean debe tener su propia anotación @Order, que se aplica dentro de un conjunto de varias coincidencias para el tipo concreto de bean devuelto por el método de fábrica.
La anotación estándar jakarta.annotation.Priority no está disponible en el nivel de @Bean, porque no puede declararse en métodos. Su semántica puede modelarse mediante valores de @Order combinados con @Primary o @Fallback en un único bean para cada tipo.
También pueden autoconectarse instancias de Map tipadas siempre que el tipo de clave esperado sea String. Los valores del mapa son todos los beans del tipo esperado y las claves son los nombres de bean correspondientes:
public class MovieRecommender {
private Map<String, MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
}
De forma predeterminada, la autoconexión falla cuando no hay beans candidatos coincidentes para un punto de inyección. En el caso de un array, una colección o un mapa declarados, se espera al menos un elemento coincidente.
Dependencias opcionales
El comportamiento predeterminado trata los métodos y campos anotados como dependencias obligatorias. Puedes cambiarlo estableciendo el atributo required de @Autowired en false, lo que permite que el framework omita un punto de inyección que no se puede satisfacer:
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired(required = false)
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// ...
}
Un método no obligatorio no se invoca si su dependencia —o cualquiera de sus dependencias, si tiene varios argumentos— no está disponible. Un campo no obligatorio tampoco se rellena en ese caso y conserva su valor predeterminado.
En otras palabras, asignar false al atributo required indica que la propiedad correspondiente es opcional a efectos de autoconexión e ignora la propiedad si no puede autoconectarse. Esto permite asignar valores predeterminados que pueden sobrescribirse opcionalmente mediante inyección de dependencias.
Los argumentos de constructores y de métodos de fábrica inyectados son un caso especial, porque el atributo required de @Autowired tiene un significado algo diferente debido al algoritmo de resolución de constructores de Spring.
Los argumentos de constructores y métodos de fábrica son obligatorios de forma efectiva por defecto, aunque existen algunas reglas especiales cuando hay un único constructor. Por ejemplo, los puntos de inyección con varios elementos —arrays, colecciones y mapas— se resuelven como instancias vacías si no hay beans coincidentes disponibles.
Esto permite un patrón de implementación habitual en el que todas las dependencias se declaran en un único constructor con varios argumentos, por ejemplo, en un único constructor público sin anotación @Autowired.
Solo un constructor de una clase de bean determinada puede declarar @Autowired con el atributo required establecido en true, indicando el constructor que se debe autoconectar al utilizarlo como bean de Spring. En consecuencia, si el atributo required conserva su valor predeterminado true, solo puede anotarse un constructor con @Autowired.
Si varios constructores declaran la anotación, todos deben declarar required=false para considerarse candidatos de autoconexión, de forma análoga a autowire=constructor en XML. Se elegirá el constructor con el mayor número de dependencias que puedan satisfacerse mediante beans coincidentes en el contenedor de Spring. Si no se puede satisfacer ninguno de los candidatos, se utiliza un constructor principal o predeterminado, cuando exista.
De manera similar, si una clase declara varios constructores pero ninguno está anotado con @Autowired, se utiliza un constructor principal o predeterminado, cuando exista. Si una clase solo declara un constructor, siempre se utiliza, incluso sin anotación. Un constructor anotado no tiene que ser público.
Como alternativa, puedes expresar que una dependencia concreta no es obligatoria mediante java.util.Optional:
public class SimpleMovieLister {
@Autowired
public void setMovieFinder(Optional<MovieFinder> movieFinder) {
// ...
}
}
También puedes utilizar una anotación @Nullable a nivel de parámetro —de cualquier tipo y en cualquier paquete; por ejemplo, org.jspecify.annotations.Nullable de JSpecify—:
public class SimpleMovieLister {
@Autowired
public void setMovieFinder(@Nullable MovieFinder movieFinder) {
// ...
}
}
Dependencias reconocidas por el contenedor
También puedes utilizar @Autowired con interfaces que Spring reconoce como dependencias resolubles: BeanFactory, ApplicationContext, Environment, ResourceLoader, ApplicationEventPublisher y MessageSource.
Estas interfaces y sus interfaces extendidas, como ConfigurableApplicationContext o ResourcePatternResolver, se resuelven automáticamente, sin necesidad de configuración especial. El siguiente ejemplo autoconecta un objeto ApplicationContext:
public class MovieRecommender {
@Autowired
private ApplicationContext context;
public MovieRecommender() {
}
// ...
}
Las anotaciones @Autowired, @Inject, @Value y @Resource las procesan implementaciones de BeanPostProcessor de Spring. Esto significa que no puedes aplicar estas anotaciones dentro de tus propios tipos BeanPostProcessor o BeanFactoryPostProcessor.
Estos tipos deben conectarse explícitamente mediante XML o un método @Bean de Spring.