Получить доступ

Как корректно получать prototype-бин внутри singleton-бина, чтобы каждый раз создавался новый экземпляр?

SeniorКонтейнер изнутриSpring
Ещё спрашивают так:
  • Почему prototype-бин внутри singleton всегда один и тот же?
Коротко

Singleton создаётся один раз, и prototype внедряется в него один раз — «застывает». Новый экземпляр при каждом использовании дают **ObjectProvider<T>.getObject(), @Lookup-метод или scoped proxy**.

  • ObjectProvider — проще и явнее всего
  • @Lookup — Spring переопределяет метод через CGLIB
  • scoped proxy — прокси создаёт новый объект на каждый вызов метода (часто не то, что нужно)

А ещё Если нужен «новый объект на запрос» — request scope

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Если prototype-бин внедрить в singleton обычным конструкторным DI, Spring разрешит зависимость ОДИН раз — при создании singleton-а, и дальше будет один и тот же экземпляр, несмотря на prototype-scope. Чтобы получать новый экземпляр на каждое обращение, нужен явный запрос у контейнера: ObjectProvider<T> (objectProvider.getObject()) или jakarta.inject.Provider<T>, либо @Lookup-метод, либо scoped-proxy (@Scope(proxyMode=TARGET_CLASS)). Это распространённый вопрос на понимание того, что scope бина действует при разрешении зависимости, а не при каждом её использовании.

Что хотят услышать

  • Почему prototype не пересоздаётся.
  • Три способа и их различия.

Частые ошибки

  • Ждать нового prototype-экземпляра от обычного field/constructor-внедрения в singleton.
  • Путать lifecycle prototype-бина (Spring не управляет его уничтожением) с singleton.

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✓Через ObjectProvider/Provider (или lookup-метод/scoped proxy): обычное конструкторное внедрение даст один и тот же экземпляр, зафиксированный при создании singleton-а
  • ✗Просто внедрить prototype через конструктор — Spring сам создаст новый при каждом обращении
  • ✗Пометить singleton аннотацией @Prototype
  • ✗Вызвать System.gc() перед обращением к бину

Что спросят дальше

  • Почему Spring не вызывает destroy у prototype-бинов?
  • Что делает scoped proxy?

Разбор темы

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем