스프링 web-mvc, Controller에서 HttpServletRequest 을 주입받아 사용하는게 가능할까?
스프링은 기본적으로 대부분의 Bean
을 싱글톤 인스턴스화 해서 등록한다.
그렇다면 위와 같은 코드의 HttpServletRequest
의존성 주입은 정상 동작할까? 아니, 애초에 HttpServletRequest
가 Bean
으로 등록이 되는걸까?
각 요청에 대해서 HttpServletRequest
정보가 달라질것 같은데 의존성 주입된 HttpServletRequest
는 안전할까?
결론적으로는 안전하다.
의존성 주입되어 사용되는 HttpServletRequest
는 Proxy
객체로써 내부적으론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
내에 빈으로 정의되지 않은 것을 주입하기 위해 사용된다고 한다.
아하 . RequestObjectFactory
는 ObjectFactory
를 구현하여 currentRequestAttributes() ← RequestContextHolder.currentRequestAttributes()
를 통해 RequestAttributes
객체를 리턴하고 있다.
RequestObjectFactory
의 getObject
는 RequestContextHolder
를 통해 Thread별로 저장된 RequestAttributes
객체를 리턴받는다.
… 그치만 단순히 factory를 통해 주입해버린다면 안전하지 않은데.
어딘가 proxy 로 wrapping 해서 주입하는 곳이 있지 않나? 어디서 할까?
앞서beanFactory
의 registerResolvableDependency
메서드로 의존성 주입 대상과 factory를 등록했다.
proxy로 wrapping해서 주입해주는 곳도 마찬가지로 beanFactory
내에 존재한다.
발췌한 코드의 7 번 라인을 보면 resolvableDependencies Collection
(의존 주입을 위해 factory로 등록한) 을 loop 돌면서 의존성 주입 객체를 생성해서 맵핑하고 있다. 그리고 아래와 같이 주입할 객체를 생성하고 있다.AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
AutowireUtils.resolveAutowiringValue
메서드를 보면 jdk dynamicProxy
를 통해 프록시 객체를 리턴한다.
* 의존성 타입이 interface가 아니면 프록시가 아닌 factory를 통해 생성한 객체를 리턴한다.
팩토리 구현체인 ObjectFactoryDelegatingInvocationHandler
내용은 ObjectFactory
의 getObject()
로 리턴된 객체를 proxy method invoke 하고 있다.
위에서 따라가본 코드들을 통해 확인했을 때.
spring은 @Autowired HttpServletRequest
에 대해 RequestContextHolder
의 HttpServletRequest
를 접근하는 Proxy
객체를 생성하여 주입하는 것을 확인할 수 있었다.