Рубрики
Без рубрики

Spring NoSuchBeanDefinitionException

Причины и решения для исключения NoSuchBeanDefinitionException весной – “Нет квалифицирующего компонента типа”, “Нет именованного компонента”, проксированных компонентов и т. Д.

Автор оригинала: Eugen Paraschiv.

1. Обзор

В этой статье мы обсуждаем Spring org.springframework.beans.factory.NoSuchBeanDefinitionException – это обычное исключение, создаваемое BeanFactory при попытке разрешить компонент, который просто не определен в контексте Spring.

Мы проиллюстрируем возможные причины этой проблемы и доступные решения.

И, конечно, исключения случаются, когда вы меньше всего их ожидаете; посмотрите полный список исключений и решений весной .

Дальнейшее чтение:

Учебник по весенним исключениям

Весеннее BeanCreationException

2. Причина: Нет квалифицирующего компонента типа […] Найдено для зависимости

Наиболее распространенной причиной этого исключения является просто попытка ввести компонент, который не определен. Например – BeanB подключается к соавтору – BeanA:

@Component
public class BeanA {

    @Autowired
    private BeanB dependency;
    //...
}

Теперь, если зависимость – BeanB – не определена в контексте Spring, процесс начальной загрузки завершится неудачей с исключением определения такого компонента/|:

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

Причина четко указана весной: ” ожидается, что по крайней мере 1 компонент, который квалифицируется как кандидат autowire для этой зависимости

Одна из причин , по которой BeanB может не существовать в контексте – если бобы автоматически выбираются сканированием classpath и если BeanB правильно аннотирован как боб ( @Component , @Repository , @Service , @Controller и т. Д.), – заключается в том, что он может быть определен в пакете, который не сканируется Spring :

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

В то время как сканирование путей к классам может быть настроено следующим образом:

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

Если бобы не сканируются автоматически с помощью , определенного вручную , то BeanB просто не определен в текущем контексте Spring.

3. Причина: Поле […] в […] Требуется компонент типа […] Этого Не Удалось Найти

В приложении Spring Boot для описанного выше сценария мы получаем другое сообщение.

Давайте возьмем тот же пример, где Bean подключен к Beans , но он не определен:

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

Если мы попытаемся запустить это простое приложение, которое попытается загрузить Beans :

@SpringBootApplication
public class NoSuchBeanDefinitionDemoApp {

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

Приложение не запустится с сообщением об ошибке:

***************************
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.

Здесь com.baeldung.spring boot mvc.nosuchbeandefinitionexception является пакетом для BeanA , BeanB и NoSuchBeanDefinitionDemoApp .

Фрагмент кода для этого примера можно найти в этом проекте Github.

4. Причина: Нет квалифицирующего боба типа […] Определяется

Другой причиной исключения является существование двух определений компонентов в контексте вместо одного. Например, если интерфейс – IBeanB реализован двумя компонентами – BeanB1 и BeanB2 :

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

Теперь, если Bean автоматически подключит этот интерфейс, Spring не будет знать, какую из двух реализаций внедрить:

@Component
public class BeanA {

    @Autowired
    private IBeanB dependency;
    ...
}

И снова это приведет к тому, что NoSuchBeanDefinitionException будет вызвано 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

Аналогично, Spring четко указывает причину сбоя проводки: “ожидался один соответствующий боб, но найдено 2” .

Обратите внимание, однако, что в этом случае создается точное исключение не NoSuchBeanDefinitionException , а подкласс – исключение NoUniqueBeanDefinitionException . Это новое исключение было введено весной 3.2.1 именно по этой причине – чтобы провести различие между причиной , по которой не было найдено определение компонента, и этой причиной, по которой в контексте найдено несколько определений.

До этого изменения исключение, приведенное выше, было:

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

Одним из решений этой проблемы является использование @квалификатора аннотации для точного указания имени компонента, который мы хотим передать:

@Component
public class BeanA {

    @Autowired
    @Qualifier("beanB2")
    private IBeanB dependency;
    ...
}

Теперь у Spring достаточно информации, чтобы принять решение о том, какой боб вводить – BeanB1 или BeanB2 (имя по умолчанию BeanB2beanB2 ).

5. Причина: Боб Не назван […] Определяется

Исключение NoSuchBeanDefinitionException также может быть вызвано, когда компонент, который не определен, запрашивается по имени из контекста Spring:

@Component
public class BeanA implements InitializingBean {

    @Autowired
    private ApplicationContext context;

    @Override
    public void afterPropertiesSet() {
        context.getBean("someBeanName");
    }
}

В этом случае нет определения компонента для “someBeanName”, что приводит к следующему исключению:

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

Опять же, Spring четко и лаконично указывает причину сбоя: ” Не определен боб с именем X “.

6. Причина: Проксированные бобы

Когда компонент в контексте проксируется с помощью механизма динамического прокси JDK, то прокси не будет расширять целевой компонент (однако он будет реализовывать те же интерфейсы).

Из-за этого, если боб вводится интерфейсом, он будет правильно подключен. Однако если компонент вводится фактическим классом, то Spring не найдет определение компонента, соответствующее классу, поскольку прокси – сервер фактически не расширяет класс.

Очень распространенной причиной, по которой боб может быть проксирован, является поддержка транзакций Spring , а именно бобы, аннотированные @Transactional .

Например, если Service вводит Service , и обе службы являются транзакционными, ввод по определению класса не будет работать:

@Service
@Transactional
public class ServiceA implements IServiceA{

    @Autowired
    private ServiceB serviceB;
    ...
}

@Service
@Transactional
public class ServiceB implements IServiceB{
    ...
}

Те же две службы, на этот раз правильно вводимые интерфейсом , будут в порядке:

@Service
@Transactional
public class ServiceA implements IServiceA{

    @Autowired
    private IServiceB serviceB;
    ...
}

@Service
@Transactional
public class ServiceB implements IServiceB{
    ...
}

7. Заключение

В этом учебном пособии рассматриваются примеры возможных причин для общего NoSuchBeanDefinitionException – с акцентом на том, как устранить эти исключения на практике.

Примеры реализации всех этих исключений можно найти в проекте GitHub – это проект на основе Eclipse, поэтому его должно быть легко импортировать и запускать как есть.

Наконец, полный список исключений и решений весной может стать хорошим ресурсом для закладки.