본문 바로가기

Web/웹 상식

HandlerMethodArgumentResolver에 대해서

Spring을 활용해서 웹 개발을 하던 중 의문이 생겼습니다.

Controller에서 Parameter를 받을 때 Model을 넣어주면 해당 Model의 생성자는 어디에 있지?

객체가 생성되어 있고 값이 들어가 있는데 생성자는 어디에 있는지 알 수가 없었습니다. 그러다 찾은 것이 HandlerMethodArgumentResolver입니다. 

 

HandlerMethodArgumentResolver

Spring에서 제공하는 인터페이스 중 하나로 컨트롤러에서 특정 조건에 맞는 파라미터에 원하는 값을 바인딩 해주는 역할을 합니다.

 

위의 상황과 같이 Model이 파라미터라면 모델 객체를 생성하고 값을 넣어서 반환해주는 것이 이 인터페이스의 역할입니다.

 

Custom HandlerMethodArgumentResolver 사용하기

앞서 말한 예제인 Model을 파라미터로 받아오는 예제를 살펴보겠습니다.

 

  • Model 만들기
    public class Car {
        private String name;
        private int price;
        private int power;
        
        public String getName() {
        	return this.name;
        }
        
        public int getPrice() {
        	return this.price;
        }
        
        public int getPower() {
        	return this.power;
        }
        
        public void setName(String name) {
        	this.name = name;
        }
        
        public void setPrice(int price) {
        	this.price = price;
        }
        
        public void setPower(int power) {
        	this.power = power;
        }
    }
  • Resolver 작성
    @Component
    public class CustomHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
        
        @Override
        public boolean supportsParameter(MethodParameter methodParameter) {
            return methodParameter.getParameterType().equals(Car.class);
        }
    
        @Override
        public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
            Car car = new Car();
            car.setName("myCar");
            car.setPrice(7000);
            car.setPower(500);
    
            return car;
        }
    }
  • Resolver 등록
    //Configuration 클래스를 분리할 경우
    
    @Configuration
    public class HandlerConfig implements WebMvcConfigurer {
        private final CustomHandlerMethodArgumentResolver customHandlerMethodArgumentResolver;
        
        @Autowired
        public HandlerConfig(CustomHandlerMethodArgumentResolver customHandlerMethodArgumentResolver) {
        	this.customHandlerMethodArgumentResolver = customHandlerMethodArgumentResolver;
        }
    
        @Override
        public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
            argumentResolvers.add(customHandlerMethodArgumentResolver);
        }
    }
    
    // SpringBoot main에 함께 적용할 경우
    
    @SpringBootApplication
    public class CustomHandlerMethodResolverApplication extends WebMvcConfigurationSupport {
        private final CustomHandlerResolver customHandlerResolver;
    
        @Autowired
        public CustomHandlerMethodResolverApplication(CustomHandlerResolver customHandlerResolver) {
            this.customHandlerResolver = customHandlerResolver;
        }
    
        @Override
        protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolverList) {
            super.addArgumentResolvers(argumentResolverList);
            argumentResolverList.add(customHandlerResolver);
        }
    
        public static void main(String[] args) {
            SpringApplication.run(CustomHandlerMethodResolverApplication.class, args);
        }
    
    }
  • 어노테이션 등록
    @Target(ElementType.PARAMETER)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface CarResolver {}​
     
    •  
    • @Target : 이 어노테이션은 선언한 어노테이션이 적용될 수 있는 위치를 결정합니다.
    • @Retention : 어노테이션이 어느 레벨까지 유지되는지를 결정합니다.
  • Controller에 사용
    @RestController
    public class CarController {
        @GetMapping("/car")
        public Car getCar(@CarResolver Car car) {
        	return car;
        }
    }

위의 예시 내용은 아래의 GitHub에 공유되어 있습니다 ㅎㅎ

https://github.com/MarrRang/CustomHandlerMethodArgumentResolverTest

 

MarrRang/CustomHandlerMethodArgumentResolverTest

Contribute to MarrRang/CustomHandlerMethodArgumentResolverTest development by creating an account on GitHub.

github.com

 

다음에...

HandlerMethodArgumentResolver를 Custom해서 사용해보기까지 했습니다. 하지만 아직 못해본것이 하나 있네요.

어노테이션 할당까지는 알겠는데 어떻게 Spring에서 알아서 Resolver를 찾아서 실행을 해주는 걸까요?

 

분명히 Resolver들을 전부 가져와서 parameter에 맞는 것을 찾아 실행해주는 invoke 실행 로직이 있을것 같습니다. 이것도 Custom 해보는 것도 가능할 것 같네요.

반응형

'Web > 웹 상식' 카테고리의 다른 글

URI와 URL의 차이  (0) 2021.08.19
[GraphQL] GraphQL 처음 시작하기  (0) 2021.08.12
Java의 직렬화란  (0) 2021.07.05
HTTP/3에 대해서  (0) 2021.06.26
Redis에 대해서  (0) 2021.06.11