Что означает scope request в Spring
Что проверяют
Знаете ли вы, что областей видимости в Spring больше двух, и понимаете ли главное следствие: как бин, живущий один запрос, попадает внутрь синглтона и не ломает его.
Как отвечать
Бин с областью request создаётся отдельно на каждый HTTP-запрос и уничтожается после его обработки, состояние разных запросов не пересекается. Область существует только в веб-контексте, в обычном ApplicationContext такого скоупа нет. Объявление короткое:
@Component
@RequestScope
public class RequestData {
private String traceId;
}Это то же самое, что @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS). Прокси тут не украшение: контроллеры и сервисы по умолчанию синглтоны и создаются один раз, поэтому прямая ссылка навсегда зафиксировала бы экземпляр первого запроса. Прокси на каждом обращении достаёт настоящий объект текущего запроса через RequestContextHolder. Альтернатива это ObjectProvider, который отдаёт бин по требованию.
Дальше полезно назвать соседей: singleton по умолчанию, prototype, session, application, websocket. И оговорить, что за уничтожение запросных бинов отвечает DispatcherServlet либо RequestContextListener.
Где спотыкаются
Внедряют запросный бин в синглтон без прокси. В лучшем случае приложение падает с жалобой на отсутствие активного запроса, в худшем всё работает, а данные подмешиваются от чужого запроса, и такой дефект ловится только под нагрузкой.
Обращаются к нему из другого потока. Контекст запроса привязан к потоку через ThreadLocal, поэтому в асинхронных задачах, в заданиях по расписанию и в реактивных цепочках его нет, а передачу контекста надо включать явно.
Считают request-скоуп способом сэкономить память. Он про изоляцию состояния, а не про скорость: прокси и поиск в контексте добавляют работу. Чаще всего честнее передать данные параметром метода, а скоуп заводить, когда один и тот же контекст нужен многим слоям сразу.