Перейти к основному содержимому

Spring BeanDefinitionStoreException

· 5 мин. чтения

1. Обзор

В этой статье мы обсудим Spring org.springframework.beans.factory.BeanDefinitionStoreException — обычно за это отвечает BeanFactory , когда определение bean-компонента недействительно, загрузка этого bean-компонента проблематична. В статье будут обсуждаться наиболее распространенные причины этого исключения, а также решения для каждой из них.

2. Причина: java.io.FileNotFoundException

Существует несколько возможных причин того, что BeanDefinitionStoreException может быть вызвано базовым IOException :

2.1. IOException Разбор XML-документа из ресурса ServletContext

Обычно это происходит в веб-приложении Spring, когда DispatcherServlet настроен в файле web.xml для Spring MVC:

<servlet>  
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>

По умолчанию Spring будет искать файл с именем springMvcServlet-servlet.xml в каталоге /WEB-INF веб-приложения.

Если этот файл не существует, будет выдано следующее исключение:

org.springframework.beans.factory.BeanDefinitionStoreException: 
Ioexception Parsing Xml Document from Servletcontext Resource [/WEB-INF/mvc-servlet.xml];
nested exception is java.io.FileNotFoundException:
Could not open ServletContext resource [/WEB-INF/mvc-servlet.xml]

Решение , конечно , состоит в том, чтобы убедиться, что файл mvc-servlet.xml действительно существует в каталоге /WEB-INF ; если нет, то можно создать образец:

<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd" >

</beans>

2.2. IOException Разбор XML-документа из ресурса пути к классу

Обычно это происходит, когда что-то в приложении указывает на несуществующий XML-ресурс или размещен не там, где должен быть.

Указание на такой ресурс может происходить различными способами.

Используя, например, конфигурацию Java, это может выглядеть так:

@Configuration
@ImportResource("beans.xml")
public class SpringConfig {...}

В XML это будет:

<import resource="beans.xml"/>

Или даже создав контекст Spring XML вручную:

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

Все это приведет к тому же исключению, если файл не существует:

org.springframework.beans.factory.BeanDefinitionStoreException: 
Ioexception Parsing Xml Document from Servletcontext Resource [/beans.xml];
nested exception is java.io.FileNotFoundException:
Could not open ServletContext resource [/beans.xml]

Решение состоит в том , чтобы создать файл и поместить его в каталог /src/main/resources проекта — таким образом, файл будет существовать в пути к классам, и он будет найден и использован Spring.

3. Причина: не удалось разрешить заполнитель…

Эта ошибка возникает, когда Spring пытается разрешить свойство, но не может — по одной из многих возможных причин.

Но сначала об использовании свойства — его можно использовать в XML:

... value="${some.property}" ...

Свойство также можно использовать в коде Java:

@Value("${some.property}")
private String someProperty;

Первое, что нужно проверить, это то, что имя свойства действительно соответствует определению свойства; в этом примере нам нужно определить следующее свойство:

some.property=someValue

Затем нам нужно проверить, где файл свойств определен в Spring — это подробно описано в моем руководстве по свойствам с помощью Spring . Хорошей практикой является размещение всех файлов свойств в каталоге /src/main/resources приложения и их загрузка через:

"classpath:app.properties"

Переходим от очевидного — еще одна возможная причина того, что Spring не может разрешить свойство, заключается в том, что в контексте Spring может быть несколько bean -компонентов PropertyPlaceholderConfigurer (или несколько элементов -заполнителей свойств )

Если это так, то решение состоит в том, чтобы либо свернуть их в один, либо настроить один в родительском контексте с ignoreUnresolvablePlaceholders .

4. Причина: java.lang.NoSuchMethodError

Эта ошибка встречается в различных формах, одна из наиболее распространенных:

org.springframework.beans.factory.BeanDefinitionStoreException:
Unexpected exception parsing XML document from ServletContext resource [/WEB-INF/mvc-servlet.xml];
nested exception is java.lang.NoSuchMethodError:
org.springframework.beans.MutablePropertyValues.add (Ljava/lang/String;Ljava/lang/Object;)
Lorg/springframework/beans/MutablePropertyValues;

Обычно это происходит, когда в пути к классам есть несколько версий Spring. Наличие более старой версии Spring случайно в пути к классам проекта встречается чаще, чем можно было бы подумать — я описал проблему и решение для этого в статье Spring Security with Maven .

Короче говоря, решение этой ошибки простое — проверьте все jar-файлы Spring в пути к классам и убедитесь, что все они имеют одинаковую версию — и эта версия 3.0 или выше.

Точно так же исключение не ограничивается bean-компонентом MutablePropertyValues — есть несколько других воплощений той же проблемы, вызванных тем же несоответствием версии:

org.springframework.beans.factory.BeanDefinitionStoreException:
Unexpected exception parsing XML document from class path resource [/WEB-INF/mvc-servlet.xml];
- nested exception is java.lang.NoSuchMethodError:
org.springframework.util.ReflectionUtils.makeAccessible(Ljava/lang/reflect/Constructor;)V

5. Причина: java.lang.NoClassDefFoundError

Распространенная проблема, аналогично связанная с Maven и существующими зависимостями Spring:

org.springframework.beans.factory.BeanDefinitionStoreException:
Unexpected exception parsing XML document from ServletContext resource [/WEB-INF/mvc-servlet.xml];
nested exception is java.lang.NoClassDefFoundError:
org/springframework/transaction/interceptor/TransactionInterceptor

Это происходит, когда функциональность транзакций настроена в конфигурации XML:

<tx:annotation-driven/>

NoClassDefFoundError означает, что поддержка транзакций Spring, а именно spring -tx , не существует в пути к классам.

Решение простое — нужно определить spring-tx в Maven pom:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>

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

Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: 
Unexpected exception parsing XML document from class path resource [/WEB-INF/mvc-servlet.xml];
nested exception is java.lang.NoClassDefFoundError:
org/aopalliance/aop/Advice

Теперь требуются следующие jar-файлы: spring-aop (и неявно aopalliance ):

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.0.RELEASE</version>
</dependency>

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

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

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