Будет ли создаваться новый объект prototype при каждом вызове метода в Spring
Что проверяют
Знаете ли вы, когда именно Spring создаёт экземпляр prototype-бина. Вопрос с подвохом, ожидаемый ответ: нет, не при каждом вызове метода. Следом просят показать, как получить действительно новый объект, и спрашивают, кто уничтожает prototype.
Как отвечать
Prototype означает новый экземпляр на каждое обращение к контейнеру: каждый getBean() и каждую точку внедрения. Вызов метода у уже полученного объекта контейнер не видит и ничего не создаёт.
Отсюда ловушка: prototype внедрён в singleton-сервис через конструктор или @Autowired. Singleton создаётся один раз, внедрение происходит один раз, и все вызовы идут в один и тот же экземпляр prototype. На практике он такой же единственный, как и его владелец.
Если новый объект действительно нужен на каждую операцию, есть такие способы:
ObjectProvider<T>: внедряете провайдер и вызываетеgetObject()там, где нужен свежий экземпляр. Самый читаемый вариант;- метод с
@Lookup: Spring переопределяет его через CGLIB и возвращает из него новый бин; jakarta.inject.Provider<T>: то же самое через стандарт JSR-330;- scoped proxy:
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS). Вот тут новый объект действительно появляется на каждый вызов метода через прокси, и это чаще баг, чем задумка: состояние между двумя вызовами теряется.
Про жизненный цикл: у prototype Spring вызывает @PostConstruct, но не вызывает @PreDestroy. После выдачи контейнер про объект забывает, и освобождать ресурсы должен тот, кто его получил.
Где спотыкаются
Отвечают «да, на каждый вызов», повторяя определение prototype, и не замечают, что бин живёт внутри singleton.
Внедряют ApplicationContext и дёргают getBean() прямо в бизнес-коде. Это работает, но привязывает код к контейнеру, а ObjectProvider решает ту же задачу чище.
Кладут в prototype соединения или файловые дескрипторы и ждут, что Spring их закроет. Метод уничтожения не вызовется, и ресурс утечёт.