Как корректно получать prototype-бин внутри singleton-бина, чтобы каждый раз создавался новый экземпляр?
- Почему prototype-бин внутри singleton всегда один и тот же?
Singleton создаётся один раз, и prototype внедряется в него один раз — «застывает». Новый экземпляр при каждом использовании дают **ObjectProvider<T>.getObject(), @Lookup-метод или scoped proxy**.
- ObjectProvider — проще и явнее всего
- @Lookup — Spring переопределяет метод через CGLIB
- scoped proxy — прокси создаёт новый объект на каждый вызов метода (часто не то, что нужно)
А ещё Если нужен «новый объект на запрос» — request scope
Подробно
Если 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.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Внедрить prototype через конструктор — Spring сам создаст новый при каждом обращении
- ✗Пометить singleton аннотацией @Prototype
- ✓Через ObjectProvider или lookup-метод, а не через конструктор
- ✗Вызвать System.gc() перед обращением к бину
Что спросят дальше
- Почему Spring не вызывает destroy у prototype-бинов?
- Что делает scoped proxy?
Разбор темы
- Контейнер: события, FactoryBean и тонкое связывание
События приложения и @EventListener, FactoryBean, Aware-интерфейсы, порядок бинов (@Order/@DependsOn) и отложенное получение (ObjectProvider/@Lazy/@Lookup).
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.