← Назад к вопросам
Что происходит в Spring, когда делаешь первый запрос
1.7 Middle🔥 131 комментариев
#Stream API и функциональное программирование#Многопоточность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что происходит в Spring при первом запросе
Первый HTTP запрос в Spring приложении инициирует сложный процесс инициализации, который включает создание контекста, регистрацию обработчиков и конфигурацию. Это критичный момент для понимания performance приложения.
Жизненный цикл Spring при первом запросе
1. Client отправляет HTTP запрос
2. DispatcherServlet перехватывает
3. ApplicationContext инициализируется (если ещё не создан)
4. Beans создаются (если ленивая инициализация)
5. HandlerMapping ищет controller
6. Controller выполняется
7. Response отправляется
1. DispatcherServlet инициализация
public class DispatcherServlet extends FrameworkServlet {
@Override
protected void service(HttpServletRequest request,
HttpServletResponse response) {
// Первый запрос
long startTime = System.nanoTime();
try {
doDispatch(request, response);
} finally {
// Логирование времени выполнения
}
}
protected void doDispatch(HttpServletRequest request,
HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
// 1. Поиск подходящего Handler
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
sendDefaultResponse(request, response); // 404
return;
}
// 2. Получение HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 3. Выполнение pre-handles (interceptors)
for (HandlerInterceptor interceptor : mappedHandler.getInterceptors()) {
if (!interceptor.preHandle(request, response,
mappedHandler.getHandler())) {
return;
}
}
// 4. Выполнение handler (controller method)
ModelAndView mv = ha.handle(processedRequest, response,
mappedHandler.getHandler());
// 5. Выполнение post-handles
for (HandlerInterceptor interceptor : mappedHandler.getInterceptors()) {
interceptor.postHandle(request, response,
mappedHandler.getHandler(), mv);
}
// 6. Рендеринг view
processDispatchResult(request, response, mappedHandler, mv, null);
}
}
2. ApplicationContext инициализация
// Если используется ленивая инициализация (lazy init)
public class ApplicationContextInitialization {
// Первый запрос может инициализировать контекст
private ApplicationContext createApplicationContext() {
// Spring сканирует:
// 1. @Configuration классы
// 2. @Component, @Service, @Repository, @Controller
// 3. Создаёт bean definitions
// 4. Разрешает зависимости
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext("com.example");
// На этом этапе:
// - Все @Bean методы выполняются
// - Все singleton beans создаются
// - Autowiring происходит
// - PostProcessors выполняются
return context;
}
// Это может занять 1-10+ секунд (cold start)
}
3. Bean Creation (если ещё не создан)
public class BeanCreationProcess {
// Типичный контроллер
@RestController
@RequestMapping("/api")
public class UserController {
@Autowired
private UserService userService; // Injection при первом использовании
@Autowired
private UserRepository userRepository;
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
// При первом запросе выполняются все инициализации
return userService.findById(id);
}
}
// Процесс создания bean:
// 1. Spring проверяет, есть ли bean UserController
// 2. Если нет, создаёт новый экземпляр
// 3. Проверяет @Autowired зависимости
// 4. Создаёт UserService (если нужен)
// 5. Создаёт UserRepository
// 6. Inject зависимости в controller
// 7. Вызывает @PostConstruct методы
}
4. Handler Mapping
public class HandlerMappingProcess {
// Spring сканирует классы с @RequestMapping
@RestController
public class UserController {
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return new User(id);
}
@PostMapping("/users")
public User createUser(@RequestBody UserRequest request) {
return new User();
}
}
// RequestMappingHandlerMapping регистрирует:
// GET /users/{id} -> UserController::getUser
// POST /users -> UserController::createUser
//
// При первом запросе это может быть динамически построено
}
5. Параметр инициализации и кэширование
public class RequestParameterHandling {
@GetMapping("/search")
public List<User> search(
@RequestParam String query,
@RequestParam(defaultValue = "0") int page,
@RequestParam(required = false) String sort) {
// Spring должен конвертировать параметры:
// - String to int для page
// - Валидировать required параметры
// - Применять дефолтные значения
// Это может быть кэшировано на следующие запросы
return Collections.emptyList();
}
}
6. Полная последовательность первого запроса
public class CompleteFirstRequestFlow {
/*
T0 - Client отправляет GET /api/users/1
T0 + 0ms:
1. DispatcherServlet.service() вызывается
2. Проверяется init флаг
3. Если не инициализирован, вызывается init()
T0 + 5ms:
4. ApplicationContext создан (если lazy)
5. Все beans созданы
6. PostProcessors выполнены
T0 + 10ms:
7. RequestMappingHandlerMapping.getHandler() вызывается
8. Ищется match для /api/users/1
9. Находится UserController::getUser
T0 + 12ms:
10. ArgumentResolvers решают параметры
11. @PathVariable Long id разрешается в 1
12. ReturnValueHandlers регистрируются
T0 + 15ms:
13. UserController.getUser(1) выполняется
14. Вызывается userService.findById(1)
15. Выполняется SQL query или cache lookup
T0 + 25ms:
16. View resolution (если REST, просто JSON)
17. HttpMessageConverter serializes ответ
18. Response отправляется
T0 + 26ms:
19. Логируется: "GET /api/users/1 200 OK в 26ms"
*/
}
7. Performance оптимизация
// ПЛОХО: ленивая инициализация при первом запросе
@SpringBootApplication
public class SlowApp {
// Контекст создаётся при первом запросе
// Первый запрос может быть очень медленным (5-30 сек)
}
// ХОРОШО: ранняя инициализация
@SpringBootApplication
public class FastApp {
public static void main(String[] args) {
// Spring Boot инициализирует контекст сразу
// При запуске (не при первом запросе)
SpringApplication.run(FastApp.class, args);
// Первый запрос будет быстрым (~50ms)
}
}
8. Что происходит под капотом
public class UnderTheHood {
public void firstRequest() {
// 1. Томкат получает запрос
// 2. Tomcat создаёт HttpServletRequest
// 3. Tomcat создаёт HttpServletResponse
// 4. DispatcherServlet.service() вызывается
// 5. FrameworkServlet.service() вызывается
// 6. Проверка: инициализирован ли контекст?
if (!initialized) {
// 7a. Инициализация контекста
initServletBean(); // Очень медленно
// 7b. Кэширование настроек
cacheHandlerMethods();
cacheArgumentResolvers();
cacheReturnValueHandlers();
}
// 8. doDispatch() - обработка запроса
doDispatch();
}
}
9. Времени выполнения типичного Spring приложения
Cold Start (первый запрос)
├── ApplicationContext init 500-2000ms
├── Bean creation 1000-5000ms
├── Handler mapping 100-500ms
├── Controller execution 10-100ms
├── Response serialization 5-50ms
└── Total 1-10 seconds
Warm Start (последующие запросы)
├── Handler lookup (cached) 0.1ms
├── Argument resolution 0.5ms
├── Controller execution 10-100ms
├── Response serialization 5-50ms
└── Total 15-150ms
10. Spring Boot optimization
@SpringBootApplication
public class OptimizedApp {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(OptimizedApp.class);
// Отключить ненужные auto-configurations
app.setAdditionalProfiles("production");
// Ранее создание контекста
app.run(args);
// Измерить time-to-ready
// Обычно 3-10 секунд для modern Spring приложения
}
}
Заключение
Первый запрос в Spring приложении инициирует:
- ApplicationContext инициализация — может быть медленной
- Bean creation и dependency injection — сканирование и создание
- HandlerMapping регистрация — сопоставление URL с контроллерами
- ArgumentResolver кэширование — преобразование параметров
- Controller execution — обработка бизнес-логики
- Response serialization — конвертация в JSON/XML
Второй и последующие запросы выполняются значительно быстрее, так как всё кэшируется. Это критично при работе с контейнерами и serverless функциями, где cold start имеет значение.