Ответ
Для каждого нового HTTP-запроса в Spring MVC создаётся отдельный экземпляр бина с областью видимости request.
Принцип работы:
- В начале обработки каждого HTTP-запроса Spring создаёт новый экземпляр такого бина.
- Все внедрения (
@Autowired) в рамках обработки одного запроса ссылаются на один и тот же объект. - После завершения обработки запроса и отправки ответа бин уничтожается сборщиком мусора.
Пример объявления:
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestScopedBean {
private String requestId = UUID.randomUUID().toString();
// Уникален для каждого запроса
}
Ключевые моменты:
- Аннотация: Используется
@Scope("request")или@RequestScope(начиная с Spring 4.3). - Проксирование (
proxyMode): Обязательно для инъекции в бины с более длительным scope (например,singleton). Прокси откладывает получение реального экземпляра до момента вызова метода. - Использование: Идеально для хранения данных, специфичных для запроса: аутентификации пользователя, параметров транзакции, временных вычислений.
Ответ 18+ 🔞
А, ну это же классика, блядь! Вечная тема, про которую каждый второй джуниор на собеседовании обосрётся, как Герасим Муму в озеро.
Смотри, суть проще пареной репы, если без этих твоих заумных слов. Представь себе столовую, ёпта.
Каждый новый голодный мудак, который приходит и орёт «Мне борща!» — это новый HTTP-запрос. И для этого конкретного распиздяя повар (то есть Spring) накрывает отдельный, новый, чистый поднос. Это и есть твой бин с областью request.
Как это работает, если по-человечески:
- Пришёл Вася — ему выкатили новый поднос. Положили ложку, вилку, хлебушек. Это его личный
RequestScopedBean. - Пока Васю кормят (обрабатывают его запрос), все повара на кухне (
@Autowired-зависимости) кладут еду именно на этот васин поднос. - Вася поел, обосрался довольный и ушёл. Поднос — нахуй в мойку. Объект уничтожается. Память свободна. Всё чисто.
Вот как это объявляется, смотри на код, не отвлекайся:
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestScopedBean {
private String requestId = UUID.randomUUID().toString();
// Этот ID будет уникальным для каждого нового подноса-запроса, ёпта!
}
А теперь главные подводные ебучки, о которые все бьются:
-
Аннотация: Можно писать
@Scope("request"). А можно, если ты не лох и у тебя Spring 4.3+, просто@RequestScope. Красиво и понятно, как Муму в мешке. -
Проксирование (
proxyMode): Вот это, блядь, самый сок! Без этого — пиздец и NullPointerException. Смотри, зачем это: у тебя есть главный шеф-повар (singleton-бин), который живёт один на всю столовую. И ты хочешь ему всучить поднос (request-бин) для Васи. Но шеф создаётся один раз при старте, а Вася со своим подносом появится только когда придёт!Вот тут и нужен прокси — хуй в пальто, обманка. Spring подсовывает шефу не реальный поднос, а его заглушку-куклу. И когда шефу реально понадобится что-то положить на поднос (вызвать метод), эта кукла-прокси скажет: «Ага, ща, погоди!», побежит, найдёт уже созданный для текущего Васи поднос и даст шефу работать с ним. Магия, блядь!
ScopedProxyMode.TARGET_CLASS— это и есть инструкция «сделай такую обманку». -
Где это применять? Да везде, где данные живут ровно один запрос! Данные авторизации пользователя, его корзина покупок на время сессии (хотя для сессии есть
sessionscope), какие-то временные вычисления, которые потом нахуй не нужны. В общем, всё, что должно умереть сразу после ответа «ОК, Вася, иди нахуй».
Короче, запомни: request scope — это одноразовый поднос для каждого нового голодраного клиента. Съел — выкинул. И не забудь про прокси, а то останешься с голой жопой и ошибкой в логах.