«1. Обзор
В этой статье мы обсуждаем Spring org.springframework.beans.factory.BeanCreationException — это очень распространенное исключение, возникающее, когда BeanFactory создает bean-компоненты из определений bean-компонентов и сталкивается с проблемой. В статье будут обсуждаться наиболее распространенные причины этого исключения вместе с решением.
2. Причина: org.springframework.beans.factory.NoSuchBeanDefinitionException
На сегодняшний день наиболее распространенной причиной BeanCreationException является попытка Spring внедрить bean-компонент, который не существует в контексте.
Например, BeanA пытается внедрить BeanB:
@Component
public class BeanA {
@Autowired
private BeanB dependency;
...
}
Если BeanB не найден в контексте, будет выдано следующее исключение (ошибка создания Bean):
Error creating bean with name 'beanA': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private com.baeldung.web.BeanB cpm.baeldung.web.BeanA.dependency;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [com.baeldung.web.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)}
Для диагностики этот тип проблемы — во-первых, убедитесь, что bean-компонент объявлен:
-
либо в файле конфигурации XML с использованием элемента \u003cbean /\u003e, либо в классе Java @Configuration с помощью аннотации @Bean, либо аннотирован с помощью: @ Компонент, @Repository, @Service, @Controller и сканирование пути к классам активно для этого пакета
Также убедитесь, что файлы конфигурации или классы действительно подбираются Spring и загружаются в основной контекст.
Further reading:
Intro to Inversion of Control and Dependency Injection with Spring
BeanNameAware and BeanFactoryAware Interfaces in Spring
Spring 5 Functional Bean Registration
3. Причина: org.springframework.beans.factory.NoUniqueBeanDefinitionException
Другой похожей причиной исключения создания компонента является попытка Spring внедрить компонент по типу, а именно по его интерфейсу, и обнаружение двух или more bean, реализующий этот интерфейс в контексте.
Например, BeanB1 и BeanB2 реализуют один и тот же интерфейс:
@Component
public class BeanB1 implements IBeanB { ... }
@Component
public class BeanB2 implements IBeanB { ... }
@Component
public class BeanA {
@Autowired
private IBeanB dependency;
...
}
Это приведет к возникновению следующего исключения фабрикой компонентов Spring:
Error creating bean with name 'beanA': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private com.baeldung.web.IBeanB com.baeldung.web.BeanA.b;
nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [com.baeldung.web.IBeanB] is defined:
expected single matching bean but found 2: beanB1,beanB2
4. Причина: org.springframework. beans.BeanInstantiationException
4.1. Custom Exception
Следующим на очереди является bean-компонент, который генерирует исключение в процессе своего создания; упрощенный пример, чтобы легко проиллюстрировать и понять проблему, вызывает исключение в конструкторе bean-компонента:
@Component
public class BeanA {
public BeanA() {
super();
throw new NullPointerException();
}
...
}
Как и ожидалось, это приведет к быстрому сбою Spring со следующим исключением:
Error creating bean with name 'beanA' defined in file [...BeanA.class]:
Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException:
Could not instantiate bean class [com.baeldung.web.BeanA]:
Constructor threw exception;
nested exception is java.lang.NullPointerException
4.2. java.lang.InstantiationException
Другим возможным случаем возникновения BeanInstantiationException является определение абстрактного класса как bean-компонента в XML; это должно быть в XML, потому что это невозможно сделать в файле Java @Configuration, а сканирование пути к классам будет игнорировать абстрактный класс:
@Component
public abstract class BeanA implements IBeanA { ... }
И XML-определение bean-компонента:
<bean id="beanA" class="com.baeldung.web.BeanA" />
Эта установка приведет к аналогичному исключению:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'beanA' defined in class path resource [beansInXml.xml]:
Instantiation of bean failed;
nested exception is org.springframework.beans.BeanInstantiationException:
Could not instantiate bean class [com.baeldung.web.BeanA]:
Is it an abstract class?;
nested exception is java.lang.InstantiationException
4.3. java.lang.NoSuchMethodException
Если у bean-компонента нет конструктора по умолчанию, и Spring пытается создать его экземпляр, ища этот конструктор, это приведет к исключению во время выполнения; например:
@Component
public class BeanA implements IBeanA {
public BeanA(final String name) {
super();
System.out.println(name);
}
}
Когда этот bean-компонент подхватывается механизмом сканирования пути к классам, ошибка будет следующей:
Error creating bean with name 'beanA' defined in file [...BeanA.class]: Instantiation of bean failed;
nested exception is org.springframework.beans.BeanInstantiationException:
Could not instantiate bean class [com.baeldung.web.BeanA]:
No default constructor found;
nested exception is java.lang.NoSuchMethodException: com.baeldung.web.BeanA.<init>()
Аналогичное исключение, но его сложнее диагностировать, может возникнуть, когда Spring зависит от пути к классам не имеют той же версии; такая несовместимость версий может привести к исключению NoSuchMethodException из-за изменений API. Решение такой проблемы — убедиться, что все библиотеки Spring имеют одну и ту же версию в проекте.
5. Причина: org.springframework.beans.NotWritablePropertyException
Еще одна возможность заключается в определении bean-компонента — BeanA — со ссылкой на другой bean-компонент — BeanB — без соответствующего метода установки в BeanA:
@Component
public class BeanA {
private IBeanB dependency;
...
}
@Component
public class BeanB implements IBeanB { ... }
И конфигурация Spring XML:
<bean id="beanA" class="com.baeldung.web.BeanA">
<property name="beanB" ref="beanB" />
</bean>
Опять же, это может произойти только в конфигурации XML, потому что при использовании Java @Configuration компилятор сделает невозможным воспроизведение этой проблемы.
Конечно, чтобы решить эту проблему, необходимо добавить сеттер для IBeanB:
@Component
public class BeanA {
private IBeanB dependency;
public void setDependency(final IBeanB dependency) {
this.dependency = dependency;
}
}
6. Причина: org.springframework.beans.factory.CannotLoadBeanClassException
Это исключение возникает, когда Spring не может загрузить класс определенного bean-компонента — это может произойти, если Spring XML Configuration содержит bean-компонент, у которого просто нет соответствующего класса. Например, если класс BeanZ не существует, следующее определение приведет к исключению:
<bean id="beanZ" class="com.baeldung.web.BeanZ" />
«
nested exception is org.springframework.beans.factory.BeanCreationException:
...
nested exception is org.springframework.beans.factory.CannotLoadBeanClassException:
Cannot find class [com.baeldung.web.BeanZ] for bean with name 'beanZ'
defined in class path resource [beansInXml.xml];
nested exception is java.lang.ClassNotFoundException: com.baeldung.web.BeanZ
«Основная причина, если ClassNotFoundException и полное исключение в этом случае:
7. Потомки BeanCreationException
7.1. org.springframework.beans.factory.BeanCurrentlyInCreationException
@Component
public class BeanA implements IBeanA {
private IBeanB beanB;
@Autowired
public BeanA(final IBeanB beanB) {
super();
this.beanB = beanB;
}
}
@Component
public class BeanB implements IBeanB {
final IBeanA beanA;
@Autowired
public BeanB(final IBeanA beanA) {
super();
this.beanA = beanA;
}
}
Одним из подклассов BeanCreationException является BeanCurrentlyInCreationException; это обычно происходит при использовании внедрения конструктора — например, в случае циклических зависимостей:
org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'beanA':
Requested bean is currently in creation: Is there an unresolvable circular reference?
Spring не сможет разрешить такой сценарий подключения, и конечный результат будет таким: ~ Полное исключение очень подробное:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'beanA' defined in file [...BeanA.class]:
Unsatisfied dependency expressed through constructor argument with index 0
of type [com.baeldung.web.IBeanB]: :
Error creating bean with name 'beanB' defined in file [...BeanB.class]:
Unsatisfied dependency expressed through constructor argument with index 0
of type [com.baeldung.web.IBeanA]: :
Error creating bean with name 'beanA': Requested bean is currently in creation:
Is there an unresolvable circular reference?;
nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'beanA':
Requested bean is currently in creation:
Is there an unresolvable circular reference?;
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'beanB' defined in file [...BeanB.class]:
Unsatisfied dependency expressed through constructor argument with index 0
of type [com.baeldung.web.IBeanA]: :
Error creating bean with name 'beanA':
Requested bean is currently in creation:
Is there an unresolvable circular reference?;
nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'beanA':
Requested bean is currently in creation: Is there an unresolvable circular reference?
7.2. org.springframework.beans.factory.BeanIsAbstractException
Это исключение создания экземпляра может возникнуть, когда фабрика компонентов пытается получить и создать экземпляр компонента, который был объявлен как абстрактный; например:
public abstract class BeanA implements IBeanA {
...
}
Объявлено в конфигурации XML как:
<bean id="beanA" abstract="true" class="com.baeldung.web.BeanA" />
Теперь, если мы попытаемся получить BeanA из контекста Spring по имени — например, при создании экземпляра другого компонента:
@Configuration
public class Config {
@Autowired
BeanFactory beanFactory;
@Bean
public BeanB beanB() {
beanFactory.getBean("beanA");
return new BeanB();
}
}
~ ~~ Это приведет к следующему исключению:
org.springframework.beans.factory.BeanIsAbstractException:
Error creating bean with name 'beanA': Bean definition is abstract
И полная трассировка стека исключения:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'beanB' defined in class path resource
[org/baeldung/spring/config/WebConfig.class]: Instantiation of bean failed;
nested exception is org.springframework.beans.factory.BeanDefinitionStoreException:
Factory method
[public com.baeldung.web.BeanB com.baeldung.spring.config.WebConfig.beanB()] threw exception;
nested exception is org.springframework.beans.factory.BeanIsAbstractException:
Error creating bean with name 'beanA': Bean definition is abstract
8. Заключение
В конце этой статьи у нас должна быть четкая карта для навигации по различные причины и проблемы, которые могут привести к BeanCreationException в Spring, а также хорошее понимание того, как исправить все эти проблемы.
Реализацию всех примеров исключений можно найти в проекте github — это проект на основе Eclipse, поэтому его легко импортировать и запускать как есть.