둘셋 개발!

[Spring] @Controller사용시 핸들러의 파라미터는 누가 넣어주는 걸까? 본문

SPRING

[Spring] @Controller사용시 핸들러의 파라미터는 누가 넣어주는 걸까?

23 2023. 8. 18. 22:57

@Controller을 사용할 때 각 핸들러 메서드에 다양한 파라미터값을 넣으면서 편하게 데이터를 불러올 수 있다.

대표적인 파라미터로는 @RequestParam, @PathValiable, @RequestBody, @ModelAttribute, Model,... 등등 이 있다.

해당 핸들러 메서드의 파라미터를 보고 데이터를 넣어주는 것은 누가 하는것일까??

 

바로 ArgumentResolver다.

Argument는 전달인자   Resolver는 해결하다라는 의미를 가지고 있으니, 전달인자를 해결해주는 녀석이다.

 

코드를 보면

HandlerMethodArgumentResolver


동작 방식

1. @RequestMapping을 사용했음으로 RequestMapping 핸들러 어댑터를 호출

2. 호출할 핸들러 정보를 바탕으로 맞는 파라미터 값을 넣기 위해 ArgumentResolver 사용

3. 파라미터와 함께 핸들러를 호출

 


실제 코드

먼저 RequestMappingHandlerAdapter를 확인해보자.

가장 주요한 메서드 handleInternal()를 보면 된다.

코드 중간에 invokeHandlerMethod()를 호출해서 ModelAndView를 반환하는 코드가 있다.

 

RequestMappingHandlerAdapter.java의 handleInternal()의 한 부분

아마 이 코드를 실행하면서 ArguementResolver도 호출할 것이다.

invokeHandlerMethod()를 더 따라가보자

 

invokeHandlerMethod()를 보면 중간에 invokeAndeHandle을 하는 코드가 있다.

이는 메서드를 호출하고 구성된 값 중 하나를 통해 반환 값을 처리하는 코드이다.

RequestMappingHandlerAdapter.java의 invokeHandlerMethod()의 한 부분

더 들어가보면 invokeForRequest()를 하면서 Object 타입의 데이터가 나온다.

이렇게 나온 것이 우리가 원하는 그 파라미터 데이터 이다.

 

ServletInvocableHandlerMethod.java의 invokeAndHandle()의 한 부분
InvocableHandlerMethod.java의 한 부분

resolvers의 resolveArgument()하는 부분이 나온다.

거의 다 왔다.

InvocableHandlerMethod.java의 getMethodArgumentValues의 한 부분

 

코드를 보면 getArgumentResolver()를 통해서 드디어!! HandlerMethodArgumentResolver를 꺼내는 코드가 나왔다.

return을 보면 그 선택된 리졸버를 통해서 resolveArgument()를 수행하면 Object가 return되는 것을 볼 수 있다.

 

getArgumentResolver()하는 코드를 더 봐볼까요?

HandlerMethodArgumentResolverComposite.java의 resolverArgument()

 

for문을 통해 parameter을 지원하는지 체크한다 -> supportsParameter

지원한다면 선택된 리졸버를 리턴한다.

HandlerMethodArgumentResolverComposite.java의 getArgumentResolver()

 

참고로 RequestMappingHandlerAdaptor.java에 보면 다양한 파라미터를 처리해주는 resolver들을 저장하고 HandlerMethodArgumentResolverComposite의 resolvers에 저장하는 로직이 있다.

RequestMappingHandlerAdaptor.java의 한 부분
RequestMappingHandlerAdaptor.java의 한 부분

코드를 보면 RequestParam처리 리졸버, PathVariable 리졸버, RequestResponseBody리졸버, 등등 다양한 리졸버가 있다.

 

 

실제로 ArgumentResolver가 사용되는 것까지 알아봤다~~