Spring NoSuchBeanDefinitionException

1. Información general

En este artículo, estamos discutiendo la excepción Spring org.springframework.beans.factory.NoSuchBeanDefinitionException : esta es una excepción común lanzada por BeanFactory cuando se intenta resolver un bean que simplemente no está definido en el contexto Spring.

Ilustraremos las posibles causas de este problema y las soluciones disponibles.

Y, por supuesto, las excepciones ocurren cuando menos las esperas; eche un vistazo a la lista completa de excepciones y soluciones en Spring.

2. Causa: No se encontró ningún bean calificado del tipo […] para la dependencia

La causa más común de esta excepción es simplemente intentar inyectar un bean que no está definido. Por ejemplo, BeanB está conectando un colaborador, BeanA:

@Component public class BeanA { @Autowired private BeanB dependency; //... }

Ahora, si la dependencia - BeanB - no está definida en el contexto de Spring, el proceso de arranque fallará con la excepción de no definición de bean :

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.baeldung.packageB.BeanB] 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)}

Spring indica claramente la razón: "se esperaba al menos 1 bean que califica como candidato de autowire para esta dependencia "

Una razón por la que BeanB puede no existir en el contexto, si los beans se recogen automáticamente mediante el escaneo de classpath , y si BeanB está correctamente anotado como bean ( @Component , @Repository , @Service , @Controller , etc.), es que puede ser definido en un paquete que no es escaneado por Spring :

package com.baeldung.packageB; @Component public class BeanB { ...}

Si bien el escaneo de classpath se puede configurar de la siguiente manera:

@Configuration @ComponentScan("com.baeldung.packageA") public class ContextWithJavaConfig { ... }

Si los beans no se escanean automáticamente y se definen manualmente , entonces BeanB simplemente no está definido en el contexto de Spring actual.

3. Causa: el campo […] en […] requería un bean de tipo […] que no se pudo encontrar

En una aplicación Spring Boot para el escenario anterior, obtenemos un mensaje diferente.

Tomemos el mismo ejemplo donde BeanB está conectado en BeanA pero no está definido:

@Component public class BeanA { @Autowired private BeanB dependency; //... }

Si intentamos ejecutar esta sencilla aplicación, intenta cargar BeanA :

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

La aplicación no podrá iniciarse con el mensaje de error:

*************************** APPLICATION FAILED TO START *************************** Description: Field dependency in com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanA required a bean of type 'com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanB' that could not be found. Action: Consider defining a bean of type 'com.baeldung.springbootmvc.nosuchbeandefinitionexception.BeanB' in your configuration.

Aquí, com.baeldung.springbootmvc.nosuchbeandefinitionexception es el paquete para BeanA , BeanB y NoSuchBeanDefinitionDemoApp .

El fragmento de este ejemplo se puede encontrar en este proyecto de Github.

4. Causa: No se define ningún frijol calificado del tipo […]

Otra causa de la excepción es la existencia de dos definiciones de frijol en el contexto, en lugar de una. Por ejemplo, si una interfaz - IBeanB es implementada por dos beans - BeanB1 y BeanB2 :

@Component public class BeanB1 implements IBeanB { // } @Component public class BeanB2 implements IBeanB { // }

Ahora, si BeanA conecta automáticamente esta interfaz, Spring no sabrá cuál de las dos implementaciones inyectar:

@Component public class BeanA { @Autowired private IBeanB dependency; ... }

Y nuevamente, esto resultará en una NoSuchBeanDefinitionException lanzada por BeanFactory :

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.baeldung.packageB.IBeanB] is defined: expected single matching bean but found 2: beanB1,beanB2

De manera similar, Spring indica claramente la razón de la falla del cableado: "Se esperaba un solo bean coincidente pero se encontró 2" .

Tenga en cuenta, sin embargo, que en este caso, la excepción exacta que se lanza no es NoSuchBeanDefinitionException sino una subclase, la NoUniqueBeanDefinitionException . Esta nueva excepción se introdujo en Spring 3.2.1, exactamente por esta razón, para diferenciar entre la causa en la que no se encontró una definición de frijol y esta, donde se encuentran varias definiciones en el contexto.

Antes de este cambio, la excepción anterior era:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.baeldung.packageB.IBeanB] is defined: expected single matching bean but found 2: beanB1,beanB2

Una solución a este problema es usar la anotación @Qualifier para especificar exactamente el nombre del bean que queremos conectar:

@Component public class BeanA { @Autowired @Qualifier("beanB2") private IBeanB dependency; ... }

Ahora Spring tiene suficiente información para tomar la decisión de qué bean inyectar: BeanB1 o BeanB2 (el nombre predeterminado de BeanB2 es beanB2 ).

5. Causa: No se define ningún bean con nombre […]

También se puede lanzar una NoSuchBeanDefinitionException cuando se solicita un bean que no está definido por su nombre en el contexto de Spring:

@Component public class BeanA implements InitializingBean { @Autowired private ApplicationContext context; @Override public void afterPropertiesSet() { context.getBean("someBeanName"); } }

En este caso, no hay una definición de bean para "someBeanName", lo que genera la siguiente excepción:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'someBeanName' is defined

Nuevamente, Spring indica de forma clara y concisa la razón del error: “ No se define ningún bean llamado X ”.

6. Causa: Beans Proxied

Cuando un bean en el contexto es proxy usando el mecanismo de proxy dinámico JDK, entonces el proxy no extenderá el bean de destino (sin embargo, implementará las mismas interfaces).

Debido a esto, si el bean es inyectado por una interfaz, se conectará correctamente. Sin embargo, si el bean es inyectado por la clase real, Spring no encontrará una definición de bean que coincida con la clase, ya que el proxy no extender la clase.

Una razón muy común por la que el bean puede ser proxy es el soporte transaccional de Spring , es decir, beans que están anotados con @Transactional .

Por ejemplo, si ServiceA inyecta ServiceB y ambos servicios son transaccionales, la inyección según la definición de clase no funcionará:

@Service @Transactional public class ServiceA implements IServiceA{ @Autowired private ServiceB serviceB; ... } @Service @Transactional public class ServiceB implements IServiceB{ ... }

Los mismos dos servicios, esta vez inyectados correctamente por la interfaz , estarán bien:

@Service @Transactional public class ServiceA implements IServiceA{ @Autowired private IServiceB serviceB; ... } @Service @Transactional public class ServiceB implements IServiceB{ ... }

7. Conclusión

Este tutorial analizó ejemplos de las posibles causas de la NoSuchBeanDefinitionException común , con un enfoque en cómo abordar estas excepciones en la práctica.

La implementación de todos estos ejemplos de excepciones se puede encontrar en el proyecto GitHub; este es un proyecto basado en Eclipse, por lo que debería ser fácil de importar y ejecutar tal como está.

Finalmente, la lista completa de excepciones y soluciones en Spring podría ser un buen recurso para marcar.