Spring. Как это работает? Часть 2: Создание бинов через вызов конструктора

Продолжение статьи Spring. Как это работает. Часть 1
Создание бинов через вызов конструктора
Проблема
Необходимо создать бин в IoC контейнере Spring через вызов его конструктора, наиболее распространенного пути создания бинов. Эквивалентом является использование оператора new для создания объекта в Java.
Решение
Когда мы задаем атрибут class для бина, мы тем самым просим контейнер создать объект бина через вызов конструктора.
Как это работает
Предположим, что необходимо разработать приложение интернет-магазина. В первую очередь, необходимо создать класс Product с несколькими свойствами, такие как имя продукта и его цена. Поскольку в магазине существует множество продуктов, сделаем класс Product абстрактным для различных подклассов.
Затем создаем два подкласса продуктов, скажем Battery и Disc. У каждого из них определены свои свойства.
Для определения продуктов в контейнере создаем файл описания:
В случае, когда элемент <constructor-arg> не задан, будет вызван конструктор по умолчанию без аргументов. Затем, для каждого элемента <property> Spring установит значение через сеттеры. Описанная XML конфигурация аналогична такому куску кода:
В другом случае, если определен один или более элемент <constructor-arg>, Spring вызовет наиболее подходящий конструктор с таким же количеством аргументов
Приведенная конфигурация идентична такому коду:
Можете написать класс Main для теста продуктов путем получения их из контейнера:
Разрешение двусмысленности в конструкторах
Проблема
Когда указывается один или более аргументов для конструктора бина, Spring пытается найти подходящий конструктор в бине класса и передать аргументы для создания объекта бина. Однако, если аргументы применимы к более, чем одному конструктору, это может вызвать двусмысленность при выборе подходящего конструктора В этом случае, вызов подходящего конструктора может стать затруднительным действием для Spring.
Решение
Можно задать атрибуты type и index для элемента <constructor-arg> для того, чтобы помочь контейнеру найти ожидаемый конструктор.
Как это работает
Теперь добавим новый конструктор к классу SequenceGenerator с аргументами prefix и suffix.
В этом объявлении бина можно задать один или более параметров конструктора через элементы <constructor-arg>. Spring попытается найти подходящий конструктор для этого класса и передать заданные аргументы для создания объекта.
![]() |
Тег <constructor-arg> не поддерживает атрибута name. Поиск конструктора происходит в зависимости от порядка аргументов. |
Для контейнера не составит труда найти подходящий конструктор для двух аргументов, поскольку у нас описан лишь один конструктор, требующий задания двух аргументов. Предположим, что надо добавить еще один конструктор в класс SequenceGenerator с аргументами prefix и initial.
Для вызова этого конструктора необходимо сделать следующее объявление бина для передачи значений prefix и value.
Запуск примера даст результат
Причина такого неожиданного результата состоит в том, что был вызван первый конструктор с аргументами prefix и suffix. Это произошло по той причине, что Spring распознал оба аргумента как String и решил использовать первый подходящий конструктор, поскольку никакого приведения типов не требуется. Для задания ожидаемого типа аргументов можно установить его в атрибуте type для тега <constructor-arg>.
Теперь добавляем еще один конструктор в класс SequenceGenerator с аргументами initial и suffix и меняем объявление бина.
Запустив приложение, получим
Причина такого результата кроется в том, что спринг проверяет каждый конструктор на совместимость с аргументами. Но во время процедуры проверки порядок, в котором аргументы появляются в XML файле, не рассматривается. Это означает, что с точки зрения контейнера второй и третий конструктор получат одинаковое количество очков. Выбирается первый попавшийся среди подходящих.
Материалы, которые могут вас заинтересовать
- Spring. Теги на форме / Form Tags
- Spring: Контроллеры, основанные на аннотациях / Annotation Controller. Пример
- Spring SimpleFormController. Пример
- Пример Spring MVC
- Spring. Внедрение через конструктор / Constructor injection
- Spring. Внедрение через сеттер / Setter injection
- Spring. Как это работает? Часть 3
- Spring. Как это работает? Часть 1
- Spring. Базовое замещение методов при method injection








Приведенная конфигурация идентична такому коду:1Product aaa =newBattery("AAA",2.5);2aaa.setRechargeable(true);3Product cdrw =newDisc("CD-RW",1.5);4разве не Product aaa =newBattery("AAA", "2.5"); ?Отправить комментарий