du.study기록공간

@Controller handlerMethod register 본문

스프링

@Controller handlerMethod register

du.study 2020. 3. 7. 16:37
728x90

스프링 웹 프레임워크를 사용하면서 헨들러 메서드를 사용할 때, 우리는 흔히 @Controller 또는 @RestController를 사용하고 있습니다.

 

스프링에서 @Controller, @RestController 를 살펴보면 아래와 같이 되어있습니다.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {

	/**
	 * The value may indicate a suggestion for a logical component name,
	 * to be turned into a Spring bean in case of an autodetected component.
	 * @return the suggested component name, if any (or empty String otherwise)
	 * @since 4.0.1
	 */
	@AliasFor(annotation = Controller.class)
	String value() default "";

}

 

결국 @Component 어노테이션이 사용되어있는데 그렇다면 @Controller 대신 @Component를 써도 동작은 할까? (물론 맞진않지만..) 에 대한 궁금증으로 테스트를 해보게 되었습니다.

 

그 결과 실패..

 

그렇다면 왜 @Controller 는 등록이 되고 @Component는 등록이 되지않을까를 찾아보게 되었습니다.

 

해답은 AbstractHandlerMethodMapping 클레스의 initHandlerMethods()라는 부분에 찾을 수 있었는데요 빈을 등록하는과정에서 핸들러를 등록하는 부분이 바로 initHandlerMethods()입니다.

해당 코드 안을 보다보면 다음과 같은 동작을 하게됩니다.

protected void processCandidateBean(String beanName) {
	Class<?> beanType = null;
	try {
		beanType = obtainApplicationContext().getType(beanName);
	}
	catch (Throwable ex) {
		// An unresolvable bean type, probably from a lazy bean - let's ignore it.
		if (logger.isTraceEnabled()) {
			logger.trace("Could not resolve type for bean '" + beanName + "'", ex);
		}
	}
	if (beanType != null && isHandler(beanType)) {
		detectHandlerMethods(beanName);
	}	
}
    
@Override
protected boolean isHandler(Class<?> beanType) {
	return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
		AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}

해당 부분을 확인 해보면 @Controller, @RequestMapping 어노테이션을 포함하고 있을경우에만, 핸들러로 등록이되고 있었습니다. 그래서 @Component만 등록했을땐 따로 동작하지않았던것...

 

 

그렇다면 마지막으로!!

@Component에 @RequestMapping을 추가해본 결과!

이 경우 정상적으로 핸들러로 등록된것을 확인할 수 있었습니다.

 

Controller니까 당연히 @Controller를 사용하고 있었는데... 간단한 궁금증 덕분에 핸들러 메서드를 등록하는부분을 다시 살펴볼 수 있었네요

728x90
Comments