Spring BeanCreationException
1. обзор
В этой статье мы обсуждаемSpring org.springframework.beans.factory.BeanCreationException - это очень распространенное исключение, возникающее, когдаBeanFactory создает bean-компоненты определений bean-компонентов и сталкивается с проблемой. В статье будут обсуждаться наиболее распространенные причины этого исключения, а также решение.
Дальнейшее чтение:
Введение в инверсию управления и инжекцию зависимостей с помощью пружины
Краткое введение в концепции инверсии управления и внедрения зависимостей с последующей простой демонстрацией с использованием Spring Framework
Интерфейсы BeanNameAware и BeanFactoryAware в Spring
Взгляните на работу с интерфейсами BeanNameAware и BeanFactoryAware в Spring.
Spring 5 Функциональная регистрация бобов
Посмотрите, как зарегистрировать бины с помощью функционального подхода в Spring 5.
2. Причина:org.springframework.beans.factory.NoSuchBeanDefinitionException
Безусловно, наиболее распространенной причинойBeanCreationException является попытка Spring выполнитьinject a bean that doesn’t exist в контексте.
Например,BeanA пытается ввестиBeanB:
@Component
public class BeanA {
@Autowired
private BeanB dependency;
...
}
ЕслиBeanB не найден в контексте, будет выброшено следующее исключение (Ошибка создания компонента):
Error creating bean with name 'beanA': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private org.example.web.BeanB org.example.web.BeanA.dependency;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [org.example.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)}
Чтобы диагностировать этот тип проблемы - сначала убедитесь, что компонент объявлен:
-
либо в файле конфигурации XML с использованием элемента<bean />
-
или в классе Java@Configuration через аннотацию@Bean
-
или аннотируется:@Component,@Repository,@Service,@Controller, и для этого пакета активно сканирование пути к классам
Также убедитесь, что файлы конфигурации или классы действительно выбраны Spring и загружены в основной контекст.
Дальнейшее чтение:
Введение в инверсию управления и инжекцию зависимостей с помощью пружины
Краткое введение в концепции инверсии управления и внедрения зависимостей с последующей простой демонстрацией с использованием Spring Framework
Интерфейсы BeanNameAware и BeanFactoryAware в Spring
Взгляните на работу с интерфейсами BeanNameAware и BeanFactoryAware в Spring.
Spring 5 Функциональная регистрация бобов
Посмотрите, как зарегистрировать бины с помощью функционального подхода в Spring 5.
3. Причина:org.springframework.beans.factory.NoUniqueBeanDefinitionException
Другой похожей причиной исключения создания bean-компонента является попытка Spring внедрить bean-компонент по типу, а именно по его интерфейсу, и поискtwo or more bean implementing that interface в контексте.
Например,BeanB1 иBeanB2 реализуют один и тот же интерфейс:
@Component
public class BeanB1 implements IBeanB { ... }
@Component
public class BeanB2 implements IBeanB { ... }
@Component
public class BeanA {
@Autowired
private IBeanB dependency;
...
}
Это приведет к тому, что фабрика bean-компонентов 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 org.example.web.IBeanB org.example.web.BeanA.b;
nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [org.example.web.IBeanB] is defined:
expected single matching bean but found 2: beanB1,beanB2
4. Причина:org.springframework.beans.BeanInstantiationException
4.1. Пользовательское исключение
Следующим на очереди идетbean that throws an exception during its creation process; упрощенный пример, чтобы легко проиллюстрировать и понять проблему, вызывает исключение в конструкторе 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 [org.example.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-компонента:
Эта настройка приведет к похожему исключению:
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 [org.example.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);
}
}
Когда этот компонент выбирается механизмом сканирования пути к классам, сбой будет:
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 [org.example.web.BeanA]:
No default constructor found;
nested exception is java.lang.NoSuchMethodException: org.example.web.BeanA.()
Подобное исключение, но его труднее диагностировать, может возникнуть, когда зависимости Spring на пути к классам не имеютsame version; такая несовместимость версий может привести к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:
Опять же, этоcan only occur in XML Configuration, потому что при использовании 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 cannot load the class of the defined bean - это может произойти, если конфигурация Spring XML содержит компонент, у которого просто нет соответствующего класса. Например, если классBeanZ не существует, следующее определение приведет к исключению:
Основная причинаClassNotFoundException и полного исключения в этом случае:
nested exception is org.springframework.beans.factory.BeanCreationException:
...
nested exception is org.springframework.beans.factory.CannotLoadBeanClassException:
Cannot find class [org.example.web.BeanZ] for bean with name 'beanZ'
defined in class path resource [beansInXml.xml];
nested exception is java.lang.ClassNotFoundException: org.example.web.BeanZ
7. ДетиBeanCreationException
7.1. org.springframework.beans.factory.BeanCurrentlyInCreationException
Один из подклассовBeanCreationException - это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;
}
}
Spring не сможет разрешить такой сценарий подключения, и конечным результатом будет:
org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'beanA':
Requested bean is currently in creation: Is there an unresolvable circular reference?
Полное исключение очень многословно:
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 [org.example.web.IBeanB]: :
Error creating bean with name 'beanB' defined in file [...BeanB.class]:
Unsatisfied dependency expressed through constructor argument with index 0
of type [org.example.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 [org.example.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 как:
Теперь, если мы попытаемсяretrieve BeanA from the Spring Context by name - например, при создании экземпляра другого bean-компонента:
@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
И полное исключение stacktrace:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'beanB' defined in class path resource
[org/example/spring/config/WebConfig.class]: Instantiation of bean failed;
nested exception is org.springframework.beans.factory.BeanDefinitionStoreException:
Factory method
[public org.example.web.BeanB org.example.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, а также хорошее представление о том, как исправить все эти проблемы.
Реализацию всех примеров исключений можно найти вthe github project - это проект на основе Eclipse, поэтому его должно быть легко импортировать и запускать как есть.