Spring How Inject HttpServletRequest

스프링 web-mvc, Controller에서 HttpServletRequest 을 주입받아 사용하는게 가능할까?

스프링은 기본적으로 대부분의 Bean을 싱글톤 인스턴스화 해서 등록한다.
그렇다면 위와 같은 코드의 HttpServletRequest 의존성 주입은 정상 동작할까? 아니, 애초에 HttpServletRequestBean으로 등록이 되는걸까?
각 요청에 대해서 HttpServletRequest 정보가 달라질것 같은데 의존성 주입된 HttpServletRequest 는 안전할까?

결론적으로는 안전하다.
의존성 주입되어 사용되는 HttpServletRequestProxy 객체로써 내부적으론RequestContextHolder를 이용하여 HttpServletRequest를 사용하는 것과 같다
관련 : stackoverflow

그러면 어떻게 스프링에서 HttpServletRequest를 의존성 주입 하는지 따라가 보자.

GenericWebApplicationContext 등의 Web ApplicationContext 에서는
beanFactory refresh 사이클 내에 postProcessBeanFactory(..) 메서드를 호출한다.

postProcessBeanFactory에서는 WebApplicationContextUtils.registerWebApplicationScopes(..) 를 호출해서
기본 웹관련 스코프 또는 웹관련 의존성 객체 생성 factory를 등록한다.

위의 registerWebApplicationScopes(..) 메서드 블럭을 보면
ServletRequest.class 에 대해 new RequestObjectFactory()
registerResolvableDependency 로 등록하고 있다.

registerResolvableDependency()의 API 주석을 보자.

Register a special dependency type with corresponding autowired value.This is intended for factory/context references that are supposed to be autowirable but are not defined as beans in the factory: e.g. a dependency of type ApplicationContext resolved to the ApplicationContext instance that the bean is living in.Note: There are no such default types registered in a plain BeanFactory, not even for the BeanFactory interface itself.

beanFactory내에 빈으로 정의되지 않은 것을 주입하기 위해 사용된다고 한다.

아하 . RequestObjectFactoryObjectFactory를 구현하여
currentRequestAttributes() ← RequestContextHolder.currentRequestAttributes()
를 통해 RequestAttributes객체를 리턴하고 있다.

RequestObjectFactorygetObjectRequestContextHolder 를 통해 Thread별로 저장된 RequestAttributes 객체를 리턴받는다.

… 그치만 단순히 factory를 통해 주입해버린다면 안전하지 않은데.
어딘가 proxy 로 wrapping 해서 주입하는 곳이 있지 않나? 어디서 할까?

앞서
beanFactoryregisterResolvableDependency 메서드로 의존성 주입 대상과 factory를 등록했다.

proxy로 wrapping해서 주입해주는 곳도 마찬가지로 beanFactory내에 존재한다.

발췌한 코드의 7 번 라인을 보면 resolvableDependencies Collection(의존 주입을 위해 factory로 등록한) 을 loop 돌면서 의존성 주입 객체를 생성해서 맵핑하고 있다. 그리고 아래와 같이 주입할 객체를 생성하고 있다.
AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);

AutowireUtils.resolveAutowiringValue 메서드를 보면
jdk dynamicProxy를 통해 프록시 객체를 리턴한다.
* 의존성 타입이 interface가 아니면 프록시가 아닌 factory를 통해 생성한 객체를 리턴한다.

팩토리 구현체인 ObjectFactoryDelegatingInvocationHandler 내용은
ObjectFactorygetObject()로 리턴된 객체를 proxy method invoke 하고 있다.

위에서 따라가본 코드들을 통해 확인했을 때.
spring은 @Autowired HttpServletRequest에 대해
RequestContextHolderHttpServletRequest를 접근하는 Proxy 객체를 생성하여 주입하는 것을 확인할 수 있었다.

Written by

엘디는 사랑입니다.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store