Сколько экземпляров сервиса будет создано, если контроллер singleton, а сервис prototype в Spring?
Что проверяют
Понимаете ли вы, в какой момент Spring разрешает зависимости. Вопрос с подвохом: интуитивный ответ «новый экземпляр на каждый вызов» неверен, и на нём валится большинство. Хороший ответ показывает, что вы отличаете момент создания бина от момента обращения к нему и знаете штатные способы обойти ограничение.
Как отвечать
Экземпляр будет один. Контроллер создаётся единожды при старте контекста, и ровно тогда же один раз разрешается его зависимость: контейнер создаёт prototype-бин, отдаёт ссылку и больше в это не вмешивается. Дальше singleton всю жизнь работает с одним и тем же объектом, сколько бы запросов ни пришло.
Чтобы получать новый экземпляр на каждое обращение, зависимость нужно запрашивать, а не хранить:
@RestController
class OrderController {
private final ObjectProvider<OrderService> provider;
OrderController(ObjectProvider<OrderService> provider) {
this.provider = provider;
}
@PostMapping("/orders")
void create() {
provider.getObject().handle();
}
}Остальные варианты по смыслу те же: ObjectFactory, метод с @Lookup, скоуп-прокси через proxyMode = ScopedProxyMode.TARGET_CLASS, в крайнем случае прямой вызов getBean. Стоит добавить, что prototype часто и не нужен: если бин не хранит состояние, хватает singleton.
Где спотыкаются
Отвечают «на каждый вызов новый», перепутав внедрение с обращением. Внедрение произошло один раз при создании контроллера, поэтому и объект остался один.
Тащат ApplicationContext в контроллер и зовут getBean повсюду. Это ручной поиск зависимостей: класс перестаёт собираться и тестироваться без контекста Spring.
Забывают, что жизненный цикл prototype-бинов контейнер до конца не ведёт: методы с @PreDestroy у них не вызываются, и освобождать ресурсы обязан тот, кто бин запросил.