복붙노트

[SPRING] 컨트롤러에 HttpServletRequest 삽입

SPRING

컨트롤러에 HttpServletRequest 삽입

나는 기본적으로 스프링 MVC 싱글 톤의 컨트롤러를 알고있다. HttpServletRequest는 offen을 컨트롤러 핸들러 메서드에 전달합니다. 그리고 그 ok, HttpServletRequest는 요청 범위이지만, 다음과 같이 HttpServletRequest가 컨트롤러 필드에 @Autowired를 가져 오는 경우가 종종 있습니다.

@Controller("CMSProductComponentController")
@RequestMapping(CMSProductComponentController.CONTROLLER_PATH)
public class CMSProductComponentController {
    @Autowired
    private HttpServletRequest request;
}

이게 문제가 될 수 있니? 더 일반적인 질문 : 요청 범위의 구성 요소를 싱글 톤에 삽입하면 어떻게됩니까?

해결법

  1. ==============================

    1.아니요. HttpServletRequest의 경우에는 문제가되지 않으며 다른 요청 범위의 Bean에는 사용해서는 안됩니다. 기본적으로 Spring은 실제 인스턴스를 검색하는 방법을 알고있는 일종의 ObjectFactory (HttpServletRequest의 RequestObjectFactory) (YMMV)를 래핑하는 프록시 HttpServletRequest를 생성합니다. 이 프록시의 메소드를 사용하면 해당 인스턴스로 위임합니다.

    아니요. HttpServletRequest의 경우에는 문제가되지 않으며 다른 요청 범위의 Bean에는 사용해서는 안됩니다. 기본적으로 Spring은 실제 인스턴스를 검색하는 방법을 알고있는 일종의 ObjectFactory (HttpServletRequest의 RequestObjectFactory) (YMMV)를 래핑하는 프록시 HttpServletRequest를 생성합니다. 이 프록시의 메소드를 사용하면 해당 인스턴스로 위임합니다.

    더 많은 것은, 이것은 느리게 행해지므로 초기화시 실패하지 않을 것입니다. 사용 가능한 요청이 없을 때 (또는 RequestScope를 등록하지 않은 경우) bean을 사용하려고 시도하면 실패합니다.

    다음은 의견에 대한 답변이며 일반적인 설명입니다.

    @Scope 또는 XML에 해당하는 proxy-mode 특성과 관련하여 기본값은 ScopedProxyMode.NO입니다. 그러나, javadoc 상태

    요청 범위 Bean의 경우이 프록시 모드 값은 작동하지 않습니다. 원하는 구성에 따라 INTERFACES 또는 TARGET_CLASS를 사용해야합니다.

    요청 범위가 설정되면 (WebApplicationContext.SCOPE_REQUEST 상수를 사용) Spring은 RequestScope를 사용한다.

    이 간단한 예를 들어 봅시다.

    @Component
    @Scope(proxyMode = ScopedProxyMode.INTERFACES, value = WebApplicationContext.SCOPE_REQUEST)
    public class RequestScopedBean {
        public void method() {}
    }
    ...
    @Autowired
    private RequestScopedBean bean;
    

    Spring은 두 개의 bean 정의를 생성 할 것이다 : 하나는 삽입 된 bean을위한 것이고, 하나는 싱글 톤이고, 하나는 요청 범위 bean이 각각의 요청에서 생성된다.

    이 bean 정의들로부터, Spring은 싱글 톤을 당신의 목표 클래스의 타입을 가진 프록시로 초기화 할 것이다. 이 예에서는 RequestScopedBean입니다. 프록시는 필요할 때 실제 bean을 생성하거나 리턴해야하는 상태를 포함합니다. 프록시에서 메소드가 호출 될 때 예를 들어,

    bean.method();
    

    라고합니다.

    이 상태는 기본적으로 기본 BeanFactory에 대한 참조 및 요청 범위가 지정된 Bean 정의의 이름입니다. 이 두 메소드를 사용하여 새 bean을 생성 한 다음 해당 인스턴스에서 method ()를 호출합니다.

    문서 상태

    열심히로드 된 모든 요청 범위 Bean은 올바르게 구현 된 경우 프록시가됩니다. 비슷하게, 열심히로드되지 않는 범위가 지정된 요청 빈은 프록시이거나 프록시를 통해로드됩니다. 현재 스레드에 바인딩 된 HttpSerlvetRequest가 없으면 실패합니다. 기본적으로 요청 범위 Bean에 대한 Bean 종속성 체인의 어딘가에 프록시가 필요합니다.

  2. ==============================

    2.그것을 시도하면 응용 프로그램 컨텍스트 초기화 중에 BeanCreationException¹이 발생합니다. 이 오류 메시지가 HttpServletRequest와 함께 발생하지 않는 이유를 명확하게 설명합니다.

    그것을 시도하면 응용 프로그램 컨텍스트 초기화 중에 BeanCreationException¹이 발생합니다. 이 오류 메시지가 HttpServletRequest와 함께 발생하지 않는 이유를 명확하게 설명합니다.

    그래서 분명히 HttpServletRequest는 범위가 지정된 프록시입니다. 싱글 톤에서 더 작은 범위의 빈을 사용하려면 프록시 여야합니다. 이 문서는 Scoped 빈에서 더 작은 범위 종속성에 대한 의존성을 상세히 설명합니다.

    [1] : proxyMode의 기본 동작을 변경하지 않은 경우 (NO 인 경우) 또는 @Lazy를 주입하려고 시도하지 않은 경우. 후자의 경우 유효한 응용 프로그램 컨텍스트가 될 수 있지만 요청 범위가 지정된 콩이 싱글 톤과 같은 역할을합니다 (예 : 요청 범위가 지정된 bean이 싱글 톤에 주입되는 경우).

  3. from https://stackoverflow.com/questions/22674044/inject-httpservletrequest-into-controller by cc-by-sa and MIT license