Какие бинскоупы существуют в Spring
Что проверяют
Понимаете ли вы жизненный цикл бинов, а не только список названий. Главный уточняющий вопрос почти всегда один: что будет, если prototype-бин внедрить в singleton.
Как отвечать
Область видимости задаётся через @Scope или готовые аннотации. Базовые:
singleton: по умолчанию. Один экземпляр на контейнерApplicationContext, создаётся при старте контекста, если бин не помечен@Lazy. Это не синглтон из GoF: экземпляр один на контейнер и имя бина, в другом контексте будет свой;prototype: новый экземпляр на каждыйgetBean()или каждое внедрение. Контейнер создаёт и настраивает объект, но дальше за ним не следит, поэтому@PreDestroyу prototype не вызывается.
Области для веб-приложений, доступны только в веб-контексте:
request(@RequestScope): экземпляр на HTTP-запрос;session(@SessionScope): экземпляр на HTTP-сессию;application(@ApplicationScope): один наServletContext, тогда как singleton привязан к контексту Spring;websocket: на время сессии WebSocket.
Свои области регистрируют через интерфейс Scope и CustomScopeConfigurer. SimpleThreadScope есть в поставке, но по умолчанию не зарегистрирован, а refresh появляется со Spring Cloud.
Проблема короткоживущего бина внутри долгоживущего решается так: ObjectProvider<T> с вызовом getObject() при каждом использовании, метод с @Lookup или прокси через proxyMode = ScopedProxyMode.TARGET_CLASS. Аннотации @RequestScope и @SessionScope такой прокси уже включают. Обращение к request-бину из @Async или своего потока всё равно упадёт с IllegalStateException: вне потока запроса бина нет.
Где спотыкаются
Внедряют prototype в singleton через поле и ждут новый объект на каждый вызов. Внедрение происходит один раз при создании singleton, дальше всегда тот же экземпляр.
Хранят изменяемое состояние в singleton-сервисе. Бин разделяют все потоки запросов, и поле вроде currentUser превращается в гонку данных.
Называют globalSession. Эта область была для портлетов и удалена в Spring 5 вместе с их поддержкой, так что ответ выдаёт подготовку по старым статьям.