Некоторые тонкости injection’а коллекций в Spring’е
Всем привет! Меня зовут Владислав Родин. В настоящее время я преподаю на портале OTUS курсы, посвященные архитектуре ПО и архитектуре ПО, подверженного высокой нагрузке. Сейчас в OTUS’е открыт набор на новый поток курса Разработчик на Spring Framework. В преддверии старта курса я решил написать небольшой авторский материал, которым хочу поделиться с вами.
Предыстория
Spring содержит внутри себя много «магии», осуществляя самостоятельно некоторые неочевидные вещи. Незнание или непонимание этого может приводить к side-эффектам, с которыми вы можете столкнуться в процессе написания своего приложения, используя данный framework.
Одной из таких неочевидных вещей является injection интерфейсов Java Collection Framework’а. Самостоятельно наступив на грабли, связанные с этой темой, и услышав очередные вопросы от коллег, я решил с ней разобраться и зафиксировать результаты своих исследований в виде статьи с надеждой, что она кому-то поможет уже в работе или при начальном освоении Spring’а.
Сценарий
Давайте рассмотрим сервис, который будет работать с киногероями. Их будет 3: Рембо, Терминатор и Гендальф. Каждый их них будет представлять отдельный класс, а родитель у них будет общий- Hero.
public class Hero < >@Component public class Rambo extends Hero < @Override public String toString() < return "Rambo"; >> @Component public class Terminator extends Hero < @Override public String toString() < return "Terminator"; >> @Component public class Gandalf extends Hero < @Override public String toString() < return "Gandalf"; >>
Injection List’а
Давайте предположим, что мы хотим создать сервис, который будет работать с героями боевиков. Наверное, придется в него заинжектить list таких героев.
Не проблема! Создаем сервис и конфигурацию:
@Service @Getter public class ActionHeroesService < @Autowired ListactionHeroes; > @Configuration public class HeroesConfig < @Bean public Listaction() < Listresult = new ArrayList<>(); result.add(new Terminator()); result.add(new Rambo()); return result; > >
Все прекрасно, однако при проверке можно обнаружить, что в список попал и Гендальф!
Spring, увидев, что надо заинжектить List, обошел bean’ы, расположенные в context’е, нашел среди них все, подходящие под generic type, собрал из них List и заинжектил его, проигнорировав наш List.
Как заставить Spring сделать то, что мы хотим?
Вариант 1. Костыльный
Поскольку проблема именно в попытке заинжектить интерфейс Java Collection Framework’а, можно просто заменить List на ArrayList в сервисе и, конечно же, в конфигурации, чтобы Spring нашел экземпляр нужного нам класса. Тогда все будет работать так, как мы ожидали.
@Configuration public class HeroesConfig < @Bean public ArrayListaction() < ArrayListresult = new ArrayList<>(); result.add(new Terminator()); result.add(new Rambo()); return result; > > @Service @Getter public class ActionHeroesService < @Autowired ArrayListactionHeroes; >
Вариант 2. Более правильный
Еще один способ связать Spring’у руки заключается в том, что можно попросить его заинжектить в сервис не абы какой List, а bean со специальным именем, добавив Qualifier. Таким образом, нам удастся заинжектить именно наш bean.
@Service @Getter public class ActionHeroesService < @Autowired @Qualifier("action") ListactionHeroes; >
Injection Map’ы
Если про нюанс injection’а List’а многие знают, то вот с Map’ой дела обстоят как правило хуже.
Давайте напишем сервис, который будет работать с главными героями фильмов. Inject’иться в него будет Map’а, содержащая по ключам названия фильмов, а по значениям bean’ы главных героев:
@Service @Getter public class MainCharactersService < @Autowired MapmainCharactersByFilmName; > @Configuration public class HeroesConfig < @Bean public MapmainCharactersByFilmName() < Mapresult = new HashMap<>(); result.put("rambo", new Rambo()); result.put("terminator", new Terminator()); result.put("LOTR", new Gandalf()); return result; > >
При запуске же можно увидеть, что ключом Гендальфа является не LOTR, а gandalf, из чего можно сделать вывод, что записалось не название фильма, а имя bean’а, тогда как в случае с Рембо и терминатором просто повезло: имена главных героев совпадают с названиями фильмов.
На самом деле, когда необходимо заинжектить Map’у, ключом которой является String, а значением bean’ы, Spring (как и в случае с List’ом) просто проигнорирует предложенную нами Map’у, пройдется по контексту и соберет все подходящие bean’ы, и создаст Map’у с ними в качестве значений и с их именами в качестве ключей.
Варианты обхода похожи на те, которые работали для List’а:
Вариант 1. Костыльный
Заменяем Map на HashMap:
@Service @Getter public class MainCharactersService < @Autowired HashMapmainCharactersByFilmName; > @Configuration public class HeroesConfig < @Bean public HashMapmainCharactersByFilmName() < HashMapresult = new HashMap<>(); result.put("rambo", new Rambo()); result.put("terminator", new Terminator()); result.put("LOTR", new Gandalf()); return result; > >
Вариант 2. Более правильный
@Service @Getter public class MainCharactersService < @Autowired @Qualifier("mainCharactersByFilmName") MapmainCharactersByFilmName; >
Как внедрить список объектов с помощью Spring
Для этого в Spring имеются следующие средства:
- Используется для внедрения списка элементов (возможны одинаковые значения — List).
- Используется для внедрения множества значений (без дублирования значений — Set).
- В Spring можно использовать , , , для внедрения списка элементов и множества значений
- Существуют два основных способа внедрения Spring Bean: constructor-based injection и setter-based injection
- Внедрение с помощью аннотации @Autowired является популярным способом связывания зависимостей
- Аннотация @Configuration указывает, что класс содержит методы определения @Bean, которые генерируют Spring Beans для приложения
- Связывание бинов возможно над сеттерами, через поле или с помощью конструктора
- Spring Framework предоставляет гибкость, а Spring Boot упрощает разработку web-приложений
- IoC (Inversion of Control) или Dependency Injection (DI) — процесс, при котором объекты определяют свои зависимости через аргументы конструктора/фабричного метода или свойства
- Три основных способа внедрения зависимостей в класс: через конструктор, сеттер и поле
- Внедрение зависимостей — метод, широко используемый в программировании для разработки приложений и повторного использования кода
- Какие есть способы внедрить Spring Bean
- Как лучше внедрять зависимости Spring
- Что такое @configuration Spring
- Как можно связать бины Spring
- Чем отличается Spring от Springboot
- Что такое IoC в Spring
- Какие есть способы внедрения зависимостей
- Для чего нужно внедрение зависимостей
- Что можно делать на Spring
- Зачем нужны бины в Spring
- Чем отличается обычный объект от Bean
- Чем отличается Component от Bean
- Когда Spring создает proxy
- Что такое Scope в Spring
- Что такое IoC контейнер
- Чем Spring лучше Java EE
- Что такое @service Spring
- Как работает Autowired
- Какие типы конфигурации поддерживает Spring
- Какой способ di наиболее предпочтительный и почему
- Что такое Spring Dependency Injection
- Для чего нужны профили в Spring
- Что такое контекст в Spring
- Что входит в Spring
- В чем разница между @bean и @component
- Какие есть Scope в Spring
- Что можно сделать на Spring boot
Какие есть способы внедрить Spring Bean
Вариантов немного, а самых частых всего два: бин внедряется либо через конструктор класса, либо с помощью сеттера. Первое называется constructor-based injection, а второе — setter-based injection.
Как лучше внедрять зависимости Spring
Одним из самых популярных способов является внедрение с помощью аннотации @Autowired. Она может располагаться над конструктором бина (или класса конфигурации), его полем, сеттером или другим методом, принимающим в качестве аргумента другой бин.
Что такое @configuration Spring
Аннотация @Configuration является частью основной структуры фреймворка Spring. Она указывает, что класс содержит методы определения @Bean. Таким образом, контейнер Spring может обрабатывать класс и генерировать Spring Beans, которые можно использовать в приложении.
Как можно связать бины Spring
В Спринге связать бины можно различными способами:
- Связывание над сеттерами аннотацией @Autowired над ней.
- Через поле и аннотацию, которая подтянет бин в классе AppConfig.
- Так же возможно конструировать через связывание по @Autowired с помощью конструктора.
Чем отличается Spring от Springboot
Если Spring Framework фокусируется на предоставлении гибкости, то Spring Boot стремится сократить длину кода и упростить разработку web-приложения. Используя конфигурацию при помощи аннотаций и стандартного кода, Spring Boot сокращает время, затрачиваемое на разработку приложений.
Что такое IoC в Spring
Inversion of Control (IoC), также известное как Dependency Injection (DI), является процессом, согласно которому объекты определяют свои зависимости, т. е. объекты, с которыми они работают, через аргументы конструктора/фабричного метода или свойства, которые были установлены или возвращены фабричным методом.
Какие есть способы внедрения зависимостей
Есть три основных способа внедрить ваши зависимости в класс: через конструктор, сеттер и поле.
Для чего нужно внедрение зависимостей
Внедрение зависимостей (DI) — это метод, широко используемый в программировании и хорошо подходящий для разработки приложений. Следуя принципам DI, вы закладываете основу для хорошей архитектуры приложения. Внедрение внедрения зависимостей дает вам следующие преимущества: Возможность повторного использования кода
Что можно делать на Spring
Spring — это популярный фреймворк для разработки на Java, который используют для создания корпоративных приложений, например CRM. При этом применять его могут не только Java-разработчики, но и те, кто работает с Kotlin или Groovy.
Зачем нужны бины в Spring
Spring-бины − это классы, созданием экземпляров которых и установкой в них зависимостей управляет контейнер фреймворка Spring. Бины предназначены для реализации бизнес-логики приложения. Spring Bean представляет собой singleton, то есть в некотором блоке приложения существует только один экземпляр данного класса.
Чем отличается обычный объект от Bean
Бин (bean) — это не что иное, как самый обычный объект. Разница лишь в том, что бинами принято называть те объекты, которые управляются Spring-ом и живут внутри его DI-контейнера. Бином является почти все в Spring — сервисы, контроллеры, репозитории, по сути все приложение состоит из набора бинов.
Чем отличается Component от Bean
@Component — создает бины классов @Bean — можно применять только к методам, которые находятся в классе, который помечен аннотацией @Configuration.
Когда Spring создает proxy
Когда spring определяет, что bean Test советует одним или несколькими аспектами, он автоматически генерирует для него прокси, чтобы перехватывать все вызовы методов и выполнять дополнительную логику, когда это необходимо.
Что такое Scope в Spring
Атрибут scope — это строка-идентификатор, которая ставит бину в соответствие экземпляр класса org.
Что такое IoC контейнер
Если сравнить с более низкоуровневыми технологиями, IoC-контейнер — это компоновщик, который собирает не объектные файлы, а объекты ООП (экземпляры класса) во время исполнения программы. Очевидно, для реализации подобной идеи было необходимо создать не только сам компоновщик, но и фабрику, производящую объекты.
Чем Spring лучше Java EE
Проще говоря, Java EE — для легко масштабируемого монолитного приложения, Spring — для совсем маленьких приложений с GUI на Front-end или для микросервисной архитектуры. Ваши программисты могут и не знать стека Java EE. Как показала моя практика — учатся они ему очень быстро.
Что такое @service Spring
@Service — (Сервис-слой приложения) Аннотация, объявляющая, что этот класс представляет собой сервис — компонент сервис-слоя. Сервис является подтипом класса @Component. Использование данной аннотации позволит искать бины-сервисы автоматически.
Как работает Autowired
Принцип её работы очень прост. И при создании контекста Spring автоматически определит, что для создания MyService требуется bean типа ServiceDependency (или наследник), найдёт его у себя, в рамках подставит зависимость ServiceDependencyImpl в bean MyService.
Какие типы конфигурации поддерживает Spring
Что касается конфигурации самих бинов, у Spring есть 4 способа конфигурации:
- Xml конфигурация — ClassPathXmlApplicationContext(«context.
- Groovy конфигурация — GenericGroovyApplicationContext(»context.
- Конфигурация через аннотации с указанием пакета для сканирования — AnnotationConfigApplicationContext(«package.name»);
Какой способ di наиболее предпочтительный и почему
DI как поле класса используется редко по причине нарушения инкапсуляции, ведь внедряемое поле должно быть помечено как public. DI с помощью конструктора — наиболее предпочтительный способ осуществления DI.
Что такое Spring Dependency Injection
Внедрение зависимости (DI — Dependency injection) — это процесс предоставления программному компоненту внешней зависимости. Согласно принципу единой обязанности, объект передает «заботу» о построении нужных ему зависимостей внешнему механизму, который специально для этого предназначен.
Для чего нужны профили в Spring
Профили Spring позволяют кастомизировать приложение для работы в различном окружении. В зависимости от активного профиля можно инстанциировать различные реализации одного и того же бина, а также присваивать различные значения свойствам приложения.
Что такое контекст в Spring
ApplicationContext — это главный интерфейс в Spring-приложении, который предоставляет информацию о конфигурации приложения. Он доступен только для чтения во время выполнения, но может быть перезагружен при необходимости и поддержке приложением.
Что входит в Spring
Spring Framework включает:
- Основные технологии: внедрение зависимостей, события, ресурсы, i18n, проверка, связывание данных, преобразование типов, SpEL, AOP.
- Инструменты тестирования: mock-объекты, TestContext, Spring MVC Test, WebTestClient.
- Доступ к данным: транзакции, поддержка DAO, JDBC, ORM, Marshalling XML.
В чем разница между @bean и @component
@Component — создает бины классов @Bean — можно применять только к методам, которые находятся в классе, который помечен аннотацией @Configuration.
Какие есть Scope в Spring
В Spring Framework имеются пять возможных значений свойства scope:
- singleton.
- prototype.
- request.
- session.
- global-session.
- На данный момент мы ещё не касались Spring ApplicationContext, поэтому сейчас обсудим только singleton и prototype.
Что можно сделать на Spring boot
Что такое Spring Boot и как его использовать:
- упаковывает зависимости в starter-пакеты;
- автоматически конфигурирует приложения с помощью jar-зависимостей;
- создаёт веб-сервер, что позволяет локально запускать на нём приложения.
- Для чего метод init в Spring
- Как Spring создает прокси
- Какие есть Scope в Spring
05.04.2023 Как внедрить список объектов с помощью Spring:
В рамках фреймворка Spring имеются различные средства для внедрения списка элементов в приложение. Список может содержать одинаковые значения и внедряться с помощью средств . Кроме того, можно использовать для внедрения множества значений без дублирования. Есть также и , которые также позволяют внедрять наборы значений.
Варианты внедрения Spring Bean в приложение достаточно ограничены. Обычно используются два наиболее популярных способа: внедрение через конструктор класса (constructor-based injection) и внедрение с помощью сеттера (setter-based injection).
Одним из самых эффективных способов внедрения зависимостей Spring является использование аннотации @Autowired. Она может использоваться над конструктором бина (или класса конфигурации), сеттером или другим методом, принимающим в качестве аргумента другой бин.
Аннотация @Configuration является важной частью структуры фреймворка Spring. Она указывает на то, что класс содержит методы определения @Bean. Таким образом, контейнер Spring может обработать класс и сгенерировать Spring Beans, которые могут быть использованы в приложении.
Связывание бинов в Spring может происходить несколькими способами, например, с помощью аннотации @Autowired над сеттерами, через поле и аннотацию, которая подтягивает бин в класс AppConfig, или через связывание по @Autowired с помощью конструктора.
Spring Boot отличается от Spring Framework тем, что в первую очередь стремится сократить длину кода и упростить разработку web-приложений. Используя конфигурацию при помощи аннотаций и стандартного кода, Spring Boot сокращает время, затрачиваемое на разработку приложений.
Inversion of Control (IoC), также известное как Dependency Injection (DI), является процессом, согласно которому объекты определяют свои зависимости, т. е. объекты, с которыми они работают, через аргументы конструктора/фабричного метода или свойства, которые были установлены или возвращены фабричным методом.
Существует три основных способа внедрения зависимостей в класс: через конструктор, сеттер и поле. Они позволяют сформировать основу для хорошей архитектуры приложения. Внедрение зависимостей дает возможность повторного использования кода и является эффективным методом для разработки приложений.
Spring – Внедрение коллекций
В этом руководстве мы собираемся показать, как внедрять коллекции Java с помощью среды Spring .
Проще говоря, мы продемонстрируем примеры с интерфейсами коллекции List, Map, Set .
2. Список с @Autowired
Давайте создадим пример bean-компонента:
public class CollectionsBean @Autowired private ListString> nameList; public void printNameList() System.out.println(nameList); > >
Здесь мы объявили свойство nameList для хранения списка строковых значений .
В этом примере мы используем внедрение полей для nameList . Поэтому ставим аннотацию @Autowired .
Чтобы узнать больше о внедрении зависимостей или различных способах его реализации, ознакомьтесь с этим руководством .
После этого мы регистрируем CollectionsBean в классе настройки конфигурации:
@Configuration public class CollectionConfig @Bean public CollectionsBean getCollectionsBean() return new CollectionsBean(); > @Bean public ListString> nameList() return Arrays.asList("John", "Adam", "Harry"); > >
Помимо регистрации CollectionsBean , мы также вводим новый список, явно инициализируя и возвращая его как отдельную конфигурацию @Bean .
Теперь мы можем проверить результаты:
ApplicationContext context = new AnnotationConfigApplicationContext(CollectionConfig.class); CollectionsBean collectionsBean = context.getBean( CollectionsBean.class); collectionsBean.printNameList();
Вывод метода printNameList():
[John, Adam, Harry]
3. Установить с внедрением конструктора
Чтобы настроить тот же пример с коллекцией Set , давайте изменим класс CollectionsBean :
public class CollectionsBean private SetString> nameSet; public CollectionsBean(SetString> strings) this.nameSet = strings; > public void printNameSet() System.out.println(nameSet); > >
На этот раз мы хотим использовать внедрение конструктора для инициализации свойства nameSet . Это требует также изменений в классе конфигурации:
@Bean public CollectionsBean getCollectionsBean() return new CollectionsBean(new HashSet>(Arrays.asList("John", "Adam", "Harry"))); >
4. Карта с внедрением сеттера
Следуя той же логике, давайте добавим поле nameMap для демонстрации внедрения карты:
public class CollectionsBean private MapInteger, String> nameMap; @Autowired public void setNameMap(MapInteger, String> nameMap) this.nameMap = nameMap; > public void printNameMap() System.out.println(nameMap); > >
На этот раз у нас есть метод setter, чтобы использовать инъекцию зависимостей setter . Нам также нужно добавить код инициализации карты в класс конфигурации:
@Bean public MapInteger, String> nameMap() MapInteger, String> nameMap = new HashMap>(); nameMap.put(1, "John"); nameMap.put(2, "Adam"); nameMap.put(3, "Harry"); return nameMap; >
Результаты после вызова метода printNameMap() :
1=John, 2=Adam, 3=Harry>
5. Внедрение ссылок на компоненты
Давайте рассмотрим пример, в котором мы вводим ссылки на bean-компоненты как элементы коллекции.
Во-первых, давайте создадим bean-компонент:
public class ForEachBean private String name; // constructor >
И добавьте список ForEachBean в качестве свойства в класс CollectionsBean :
public class CollectionsBean @Autowired(required = false) private ListForEachBean> beanList; public void printBeanList() System.out.println(beanList); > >
Затем мы добавляем фабричные методы конфигурации Java для каждого элемента ForEachBean :
@Configuration public class CollectionConfig @Bean public ForEachBean getElement() return new ForEachBean("John"); > @Bean public ForEachBean getAnotherElement() return new ForEachBean("Adam"); > @Bean public ForEachBean getOneMoreElement() return new ForEachBean("Harry"); > // other factory methods >
Контейнер Spring внедряет отдельные компоненты типа ForEachBean в одну коллекцию.
Чтобы проверить это, мы вызываем метод collectionsBean.printBeanList() . Вывод показывает имена bean-компонентов в виде элементов списка:
[John, Harry, Adam]
Теперь давайте рассмотрим сценарий, когда ForEachBean отсутствует . Если в контексте приложения не зарегистрирован ForEachBean , Spring выдаст исключение из-за отсутствия требуемой зависимости.
Мы можем использовать @Autowired(required = false) , чтобы пометить зависимость как необязательную. Вместо создания исключения beanList не будет инициализирован, и его значение останется нулевым .
Если нам нужен пустой список вместо null, мы можем инициализировать beanList новым ArrayList:
@Autowired(required = false) private ListForEachBean> beanList = new ArrayList>();
5.1. Использование @Order для сортировки компонентов
Мы можем указать порядок bean-компонентов при внедрении в коллекцию .
Для этого используем аннотацию @Order и указываем индекс:
@Configuration public class CollectionConfig @Bean @Order(2) public ForEachBean getElement() return new ForEachBean("John"); > @Bean @Order(3) public ForEachBean getAnotherElement() return new ForEachBean("Adam"); > @Bean @Order(1) public ForEachBean getOneMoreElement() return new ForEachBean("Harry"); > >
Контейнер Spring сначала введет bean-компонент с именем «Harry» , так как он имеет наименьшее значение порядка.
Затем он внедрит бин «John» и, наконец, бин «Adam» :
[Harry, John, Adam]
Узнайте больше о @Order в этом руководстве .
5.2. Использование @Qualifier для выбора компонентов
Мы можем использовать @Qualifier , чтобы выбрать bean-компоненты для внедрения в конкретную коллекцию, которая соответствует имени @Qualifier .
Вот как мы используем его для точки впрыска:
@Autowired @Qualifier("CollectionsBean") private ListForEachBean> beanList;
Затем мы помечаем тем же @Qualifier bean-компоненты, которые мы хотим внедрить в список :
@Configuration public class CollectionConfig @Bean @Qualifier("CollectionsBean") public ForEachBean getElement() return new ForEachBean("John"); > @Bean public ForEachBean getAnotherElement() return new ForEachBean("Adam"); > @Bean public ForEachBean getOneMoreElement() return new ForEachBean("Harry"); > // other factory methods >
В этом примере мы указываем, что bean-компонент с именем «John» будет внедрен в список с именем «CollectionsBean» . Результаты, которые мы тестируем здесь:
ApplicationContext context = new AnnotationConfigApplicationContext(CollectionConfig.class); CollectionsBean collectionsBean = context.getBean(CollectionsBean.class); collectionsBean.printBeanList();
Из вывода мы видим, что наша коллекция имеет только один элемент:
[John]
Создание List в Spring
Выдает большой кусок текста об ошибке, но не могу понять в чем дело XML файл:
public class City < private String name; private String state; private int population; public City() < >public City(String name, String state, int population) < this.name = name; this.state = state; this.population = population; >public String getName() < return name; >public void setName(String name) < this.name = name; >public String getState() < return state; >public void setState(String state) < this.state = state; >public int getPopulation() < return population; >public void setPopulation(int population) < this.population = population; >>
Exception in thread "main" org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 9 in XML document from class path resource [Application_Context.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 9; columnNumber: 32; cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'util:list'. at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:399) at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:336) at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:304) at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:181) at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:217) at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:188) at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:252) at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:127) at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:93) at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:129) at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:537) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:452) at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139) at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83) at com.example.java.test.Main.main(Main.java:10) Caused by: org.xml.sax.SAXParseException; lineNumber: 9; columnNumber: 32; cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'util:list'. at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:204) at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:135) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:395) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:326) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:283) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:510) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3587) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:2142) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:828) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:374) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2706) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:601) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112) at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:531) at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:885) at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:821) at java.xml/com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141) at java.xml/com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243) at java.xml/com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339) at org.springframework.beans.factory.xml.DefaultDocumentLoader.loadDocument(DefaultDocumentLoader.java:76) at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadDocument(XmlBeanDefinitionReader.java:429) at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:391) . 14 more
если убрать этот List , то всё работает без проблем, понятно что дело в нем, но что именно происходит не понимаю. Только что заметил,что при использовании:
появляется похожее сообщение.