|doDispatch
|->getHandler(processRequest) : return mappedhandler
|->DisptacherServlet.handlerMappings에 대해 for loop 돌면서 request url에 대한 Handler 찾음
|->(HandlerMapping) mapping.gethandler(request) : mappedHandler 반환
|->getHandlerInternal(request)
|->super.getHandlerInternal(request) super : AbstractHandlerMethodMapping
|->initLookupPath(request) : /argument-resolver/
|->getRequestPaht(request) : requestPath
|-> requestPath.pathWithApplication.value() : /argument-resolver/
|->lookupHandlerMethod(lookupPath, request)
|->bestMatch.getHandlerMethod()
|->getHandlerInternal(request) : HandlerMethod handlerMethod 반환
|->handler가 없으면 getDefaultHandler() 호출, getDfaultHandler()도 null이면 null 반환
|->getHandlerExecutionChain() 여기서 interceptor붙임
|->cors 관련 수행
|->getHadnlerAdapter(mappeedHandler.getHandler()) : HandlerAdapter ha
|->adapter.supports(handler) handlerAdapters를 순회하며 adapter가 handler를 지원하는 지 확인
|->mappedHandler.applyPreHandler(processedRequest, response)
|->HandlerExecutionChain 내의 interceptor 순회
|->interceptor.preHandle()
|-> False일 경우 triggerAfterCompletion()
|->ha.handle(processedRequet, response, mappedHandler.getHandler() : return ModelAndview
|->handleInternal
|->invokeHandlerMethod
|->createInvocableHandlerMethod(handlerMethod) : ServletInvocableHandlerMethod invocableMethod 생성
|->invocableMethod.sethandlerMethodArgumenResolvers(this.argumentResolvers)
|->invocableMethod.setHandlerMethodRturnValueHandlers(this.returnValueHandlers)
(많이 생략)
|->invocableMethod.invokeAndHandle(webRequest, mavContainer)
|->invokeForRequest : resolve된 argument args 반환
|->getMethodArgumentValues : argument를 순회하며 argumentrResolver 적용
|->getMethodParameters()
|->this.resolvers.supportsParameter(parameter)
|->getArgumentResolver(parameter)
|->resolver.supportsParameter(parameter) for문으로 argumentResolver를 순회하며 argumentResolver가 parameter를 지원하는지 체크
|->this.argumentResolverCache.put(parameter, result)
|->resolver가 없으면 IllegaStateException 발생
|->resolveArgument()
|-> getArgumentResolver(parameter)
|-> resolver가 없으면 IllegalArgumentException 발생
|-> resolveArgument() : 처리된 argument object 반환
|->doInvoke(args)
|->method.invoke 내가 구현한 로직 실행
|->setResponseStatus
|->retunValueHandlers.handleReturnValue()
|->selectHandler()
|->returnValueHandlers를 순회하며 HandlerMethodRturnValueHandler가 returnType을 지원하는지 확인
|-> 지원하면 handler 반환
|->handlReturnValue
|->mavContainer.setViewName(viewName)
|->getModelAndView
|-> prepareResponse(response)
|->mappedHandler.applyPostHandler()
|->processDispatchResult()
|->processHandlerException(익셉션이 발생한 경우)
|->resolver.resolveExcepion() : resikver(HandlerException)을 순회하며 exMv(ModelAndView)를 반환, exMv가 있으면 순회 중단
|->doResolveException()
|->doResolveHandlerMethodException() : ExceptionHandler 기준
|->getExceptionHandlerMethod() : controller에 선언된 handlerMethod를 찾아서 ServeltInvocableHandlerMethod를 반환
|->ExceptionHandlerMethodResolver resolver = this.exceptionhandlerCache.computeIfAbsent(handlerType, ExceptionhandlerMethodResolver::new)
|->resolver.resolveMethod(exception) :만약 controller에 exceptionhandler가 있으면 반환하고 getExceptionHandlerMethod종료
|->resolveMethodByThrowable(exception)
|->getMappedMethod() : match되는 exceptionHandler아 있으면 그중 첫번째를 반환
|->mappedException.isAssignableFrom(exceptionType) : Spring app 로딩될 때 (hashmap)mappedMethods에 (exception : exceptionhandler)가 담겨있다.
|->만약 match되는 exceptoinhandler가 여러개면 ExceptionComparator로 sort한다
|->exceptionLookupCache에 저장
|->만약 controller에 설정된 ExHandler없으면 NO_MATCHING_EXCEPTION_HANDLER_METHOD반환
|->advice.isApplicableToBeanType(handlerType) : exceptionHandlerAdviceCache에 있는 advice를 순회하며 적절한 advic를 찾음
|->ExceptionHandlerMethodResolver resolver = entry.getValue()
|->resolver.resolveMethod() : 이후 로직은 위와 동일
|->invokeAndHandlerMethod() : 이후 controller의 handlerMethod처리 로직과 동일
|->ExceptionHandler가 ModelAndView를 반환하지 못한 경우 throw Exception
|->render()
|->resolveVieName()
|->view.render
|-> trigerAfterCompletion
0 = {RequestMappingHandlerMapping@10593}
1 = {WelcomePageHandlerMapping@10594}
2 = {BeanNameUrlHandlerMapping@10595}
3 = {RouterFunctionMapping@10596}
4 = {WelcomePageNotAcceptableHandlerMapping@10597}
5 = {SimpleUrlHandlerMapping@10598}
0 = {RequestMappingHandlerAdapter@10744}
1 = {HandlerFunctionAdapter@10745}
2 = {HttpRequestHandlerAdapter@10746}
3 = {SimpleControllerHandlerAdapter@10747}
0 = {WebRequestHandlerInterceptorAdapter@10808}
1 = {ConversionServiceExposingInterceptor@10878}
2 = {ResourceUrlProviderExposingInterceptor@10889}
3 = {LogInterceptor@10890} #Custorm Interceptor order(1)로 하였음에도 spring 내장 interceptor보다 순서가 뒤에 있다.
0 = {ProxyingHandlerMethodArgumentResolver@10963}
1 = {RequestParamMethodArgumentResolver@10964}
2 = {RequestParamMapMethodArgumentResolver@10965}
3 = {PathVariableMethodArgumentResolver@10966}
4 = {PathVariableMapMethodArgumentResolver@10967}
5 = {MatrixVariableMethodArgumentResolver@10968}
6 = {MatrixVariableMapMethodArgumentResolver@10969}
7 = {ServletModelAttributeMethodProcessor@10970}
8 = {RequestResponseBodyMethodProcessor@10971} -> @RequestBody 값 없으면 httpMessageNotReadableException
9 = {RequestPartMethodArgumentResolver@10972}
10 = {RequestHeaderMethodArgumentResolver@10973}
11 = {RequestHeaderMapMethodArgumentResolver@10974}
12 = {ServletCookieValueMethodArgumentResolver@10975}
13 = {ExpressionValueMethodArgumentResolver@10976}
14 = {SessionAttributeMethodArgumentResolver@10977}
15 = {RequestAttributeMethodArgumentResolver@10978}
16 = {ServletRequestMethodArgumentResolver@10979}
17 = {ServletResponseMethodArgumentResolver@10980}
18 = {HttpEntityMethodProcessor@10981}
19 = {RedirectAttributesMethodArgumentResolver@10982}
20 = {ModelMethodProcessor@10983}
21 = {MapMethodProcessor@10984}
22 = {ErrorsMethodArgumentResolver@10985}
23 = {SessionStatusMethodArgumentResolver@10986}
24 = {UriComponentsBuilderMethodArgumentResolver@10987}
25 = {LoginMemberArgumentResolver@10988} # Custom ArgumentResolver 순서 지정에 대해서는 추가 공부 필요
26 = {SortHandlerMethodArgumentResolver@10989}
27 = {PageableHandlerMethodArgumentResolver@10990}
28 = {ProxyingHandlerMethodArgumentResolver@10991}
29 = {PrincipalMethodArgumentResolver@10992}
30 = {RequestParamMethodArgumentResolver@10993}
31 = {ServletModelAttributeMethodProcessor@10994}
0 = {ModelAndViewMethodReturnValueHandler@11001}
1 = {ModelMethodProcessor@11002}
2 = {ViewMethodReturnValueHandler@11003}
3 = {ResponseBodyEmitterReturnValueHandler@11004}
4 = {StreamingResponseBodyReturnValueHandler@11005}
5 = {HttpEntityMethodProcessor@11006}
6 = {HttpHeadersReturnValueHandler@11007}
7 = {CallableMethodReturnValueHandler@11008}
8 = {DeferredResultMethodReturnValueHandler@11009}
9 = {AsyncTaskMethodReturnValueHandler@11010}
10 = {ServletModelAttributeMethodProcessor@11011}
11 = {RequestResponseBodyMethodProcessor@11012}
12 = {ViewNameMethodReturnValueHandler@11013}
13 = {MapMethodProcessor@11014}
14 = {ServletModelAttributeMethodProcessor@11015}
this.resolvers에
DefaulterrorAttributes와 HandlerExceptionResolverComposite있음
HandlerExceptionResolverComposite은 아래 리스트로 구성
0 = {ExceptionHandlerExceptionResolver@11386}
1 = {ResponseStatusExceptionResolver@11387}
2 = {DefaultHandlerExceptionResolver@11388}
3 = {MyHandlerExceptionResolver@11389} #custom Exception
Map<ControllerAdviceBean, ExceptionHandlerMethodResolver>
exceptionHandlerAdviceCache(LikedHashMap) 안에 adivce와 이에 대한 resolver가 linkedHashMap으로 mapping되어 있음
0 = {ByteArrayHttpMessageConverter@10991}
1 = {StringHttpMessageConverter@10992}
2 = {StringHttpMessageConverter@10993}
3 = {ResourceHttpMessageConverter@10994}
4 = {ResourceRegionHttpMessageConverter@10995}
5 = {SourceHttpMessageConverter@10996}
6 = {AllEncompassingFormHttpMessageConverter@10997}
7 = {MappingJackson2HttpMessageConverter@10998}
8 = {MappingJackson2HttpMessageConverter@10999}
9 = {Jaxb2RootElementHttpMessageConverter@11000}