일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 녹는다녹아
- 맛집
- 닭껍질만두
- exceptionHandler
- @ControllerAdvice
- 압구정로데오맛집
- @ExceptionHandler
- EffectiveJava
- 한우오마카세
- 이펙티브자바
- spring
- 데이트코스
- 상암동
- 아일랜드리솜
- 데이트
- 인생맛집
- Java
- JUnit5
- 서오릉
- 경기족발
- 고기김치
- 상암동맛집
- 인생소고기집
- 앤드밀
- 이속우화
- 압구정곱떡
- 청춘면가
- 토비의스프링
- 셀렉티
- 서오릉맛집
- Today
- Total
Hyeonuk_.log
[Spring] @ControllerAdvice는 어떻게 동작하는 것일까? 본문
스프링에서 @ControllerAdvice가 어떻게 동작하는지에 대해 공부해 본 결과, Spring MVC가 어떻게 돌아가는지에 대해 공부해야했다. 구글에 존재하는 많은 이미지 중, 아래의 Spring MVC Life Cycle에 대한 이미지가 DispatcherServlet 소스를 참고하기 전 이해를 도와주는데 많은 도움이 되었다.

1: User가 요청을 보낸다.
2: Filter가 이를 받아 DispatcherServlet에게 넘긴다.
3: Locale, Multipart와 같은 것들에 대한 처리.
4: Request에 대한 Controller Mapping 처리.
5: 실제 처리를 하는 Controller로 가기 전 Interceptor preHandle 처리
6~7 : Controller 내부 프로세스 처리
8: Exception이 발생하면 HandlerExceptionResolver가 해당 Exception을 처리
9. Interceptor의 postHandle 처리
10. ViewResolver에서 View 매핑
11. 실세 View Display
12. User에게 Response
위 프로세스에서 8번에 해당하는 구간에 대해 확인해볼 예정이다.
Exception이 RequestMapping 중 발생하거나 @Controller와 같은 RequestHandler에 의해 던져졌다면 DispatcherServlet은 HandlerExceptionResolver Bean들에게 처리를 위임하거나 미리 정의해놓은 Error Response와 같은(Web.xml에 <error-page>로 설정한) alternative handling을 제공한다.
아래는 DispatcherServlet의 일부이다.
public class DispatcherServlet extends FrameworkServlet {
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
....
....
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
....
....
}
private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
@Nullable Exception exception) throws Exception {
....
if (exception != null) {
if (exception instanceof ModelAndViewDefiningException) {
...
}
else {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, exception);
errorView = (mv != null);
}
}
....
}
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
@Nullable Object handler, Exception ex) throws Exception {
...
// Check registered HandlerExceptionResolvers...
ModelAndView exMv = null;
if (this.handlerExceptionResolvers != null) {
for (HandlerExceptionResolver resolver : this.handlerExceptionResolvers) {
exMv = resolver.resolveException(request, response, handler, ex);
if (exMv != null) {
break;
}
}
}
....
....
throw ex;
}
}
1. Dispatcher Servlet에 doDispatch에서 동작을 하다가 processDispatchResult로 들어간다.
2. exception이 null이면 정상처리 되고 에러가 발생(exception != null) 하면,
3. processHandlerExcpetion 으로 들어가서,
4. HandlerExceptionResolver를 받아와 resolveException을 하게 되는데
5. HandlerExceptionResolver에는 @ControllerAdvice 빈이 등록되어 주입됨
(@ControllerAdvice 어노테이션을 들어가서 한번 보면 @Component가 선언되어 있는 것을 볼 수 있다.)
(참고로 스프링 MVC 라이프사이클에서도 짐작할 수 있겠지만 Interceptor에서의 Exception은 @ControllerAdvice에서 처리되지 않는다.)
이전 글(https://blog.naver.com/lastindus/222644516492)과 이번 글을 통해서 @ControllerAdvice가 어떻게 동작하고 어떻게 사용하는지 알아보았다. 다음 포스팅에서는 @ControllerAdvice 안의 @ExceptionHandler를 사용하면서 어떻게 Exception에 대해 분류할지 더 알아보려한다.
'Dev_.log > Spring' 카테고리의 다른 글
토비의 스프링 읽다가 템플릿/콜백 기록 (0) | 2022.03.06 |
---|---|
[Junit5] @BeforeAll를 사용하다...멘붕...(토비스프링 읽다가) (0) | 2022.03.06 |
[Spring] @Service 단위테스트 (0) | 2022.02.21 |
[Spring] RestTemplate 업무 사용할 때 알아야할 점, 주의할 점 (0) | 2022.02.19 |
[Spring] @ExceptionHandler @ControllerAdvice (0) | 2022.02.18 |