13. DispatcherServlet → Controller: handle()
파라미터 준비가 끝나면, Spring MVC는 실제 컨트롤러 메서드를 호출합니다.
겉으로는 DispatcherServlet이 바로 호출하는 것처럼 보이지만, 내부적으로는 HandlerAdapter와 InvocableHandlerMethod 계층을 거칩니다.
이번 단계의 역할
준비된 파라미터를 바탕으로 실제 컨트롤러 메서드를 실행하는 단계입니다.
호출 흐름 요약
DispatcherServlet이HandlerAdapter.handle(...)를 호출합니다.RequestMappingHandlerAdapter가ServletInvocableHandlerMethod를 준비합니다.InvocableHandlerMethod가 인자를 모아doInvoke(args)를 실행합니다.- 최종적으로
method.invoke(getBean(), args)가 호출됩니다.
호출 흐름 다이어그램
sequenceDiagram
participant DS as DispatcherServlet
participant HA as RequestMappingHandlerAdapter
participant SIHM as ServletInvocableHandlerMethod
participant IHM as InvocableHandlerMethod
participant Controller
DS->>HA: handle(request, response, handler)
HA->>SIHM: invokeAndHandle(...)
SIHM->>IHM: invokeForRequest(...)
IHM->>Controller: method.invoke(bean, args)
핵심 코드
// RequestMappingHandlerAdapter.java
protected @Nullable ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
invocableMethod.invokeAndHandle(webRequest, mavContainer);
return getModelAndView(mavContainer, modelFactory, webRequest);
}
// InvocableHandlerMethod.java
protected @Nullable Object doInvoke(@Nullable Object... args) throws Exception {
Method method = getBridgedMethod();
return method.invoke(getBean(), args);
}
코드 해설
핵심은 DispatcherServlet이 직접 컨트롤러 메서드를 알지 못하고,
HandlerAdapter와 InvocableHandlerMethod가 호출 전략을 모두 담당한다는 점입니다.
설계 의도
1) 호출 전략과 프런트 컨트롤러를 분리하기 위해
DispatcherServlet은 전체 흐름만 조정하고, 구체적 메서드 호출은 어댑터 계층에 맡깁니다.
2) 파라미터 해석과 반환값 처리를 공통화하기 위해
컨트롤러 호출을 별도 계층으로 분리해야 입력/출력 처리 로직을 일관되게 적용할 수 있습니다.
다음 단계 연결
다음 문서 14번에서는 이제 실제 컨트롤러 메서드 본문 안에서 서비스 계층이 호출되는 경계를 봅니다.
← 이전: 12-3. DispatcherServlet → ExceptionHandler | 다음: 14. Controller → Service: 비즈니스 로직 호출