Какие бывают скоупы у бинов в Spring и чем отличается ApplicationScope от Singleton
Что проверяют
Знаете ли вы, где живёт экземпляр бина и кто управляет его жизненным циклом, а не только названия скоупов. Вторая часть ловит путаницу: application часто считают синглтоном на весь кластер. Следом обычно просят внедрить request-бин в синглтон.
Как отвечать
Скоупы Spring:
- singleton: по умолчанию, один экземпляр на
ApplicationContext. Создаётся при старте контекста, если не помечен@Lazy. Потокобезопасности сам по себе не даёт, поэтому изменяемое состояние в нём не хранят; - prototype: новый экземпляр при каждом запросе к контейнеру. Spring создаёт и настраивает его, но уничтожение не отслеживает,
@PreDestroyне вызовется; - request: экземпляр на HTTP-запрос;
- session: на HTTP-сессию;
- application: на
ServletContext; - websocket: на WebSocket-сессию.
Последние четыре доступны только в веб-контексте.
Теперь разница. Singleton привязан к конкретному ApplicationContext. Если в одном веб-приложении несколько контекстов (корневой и контекст DispatcherServlet или несколько сервлетов), у каждого будет свой экземпляр. Application-бин один на весь ServletContext: его видят все контексты приложения, и он хранится атрибутом ServletContext, так что до него дотянется и код вне Spring. Граница у него та же, что у одного развёрнутого приложения: между приложениями и тем более между инстансами в кластере он не разделяется. В обычном Spring Boot с одним контекстом разница почти не видна.
Внедрение короткоживущего бина в синглтон: аннотации @RequestScope, @SessionScope и @ApplicationScope по умолчанию создают прокси (ScopedProxyMode.TARGET_CLASS), и каждый вызов попадает в актуальный экземпляр. Для prototype используют ObjectProvider<T> или метод с @Lookup.
Где спотыкаются
Объясняют application как распределённый синглтон. Он живёт в памяти одной JVM и одного веб-приложения.
Внедряют prototype-бин в синглтон через конструктор и ждут новый экземпляр на каждый вызов. Внедрение происходит один раз, и prototype фактически становится синглтоном.
Хранят изменяемое состояние в синглтон-сервисе. При параллельных запросах данные одного пользователя попадают к другому.