2014-01-26 3 views
3

는 범위 내가 @Autowired자체 선언 할 필요가 HttpSession에 또는 HttpServletRequest의, 않습니다 세션 (또는 요청)와 싱글 @Component 콩 "푸"한 곳 경우, 또는 나는 그냥 --- 간단한 싱글로 유지할 수 있습니다 어떤 경우 HttpSession 및/또는 HttpServletRequest가 이미 Spring을 통해 범위가 지정된 프록시로 주입되었을 가능성이 있습니까?스프링 프록시 요청 속성이 있습니까?

답변

6

가 여기에 동작을 확인하는 아주 간단한 테스트입니다 (봄 4.0.0.RELEASE)

@Controller 
@RequestMapping("/service") 
public class NewController { 
    @RequestMapping(method = RequestMethod.GET) 
    public @ResponseBody String test(ModelMap model) { 
     System.out.println(requestEntity.request.getAttribute("type")); // get it 
     requestEntity.request.setAttribute("type", "Scope"); // set it so that we can make sure that our second request doesn't contain it 
     System.out.println(requestEntity.request.getClass()); 
     return "whatever"; 
    } 

    @Autowired 
    private Foo requestEntity; 
} 

당신이 요청을 보낼 경우, 반환되는 속성이 있음을 알게 될 것이다

@Component 
public class Foo { 
    @Autowired 
    public HttpServletRequest request; 
} 

항상 null이고 수업은 다음과 같음을 의미합니다.

class com.sun.proxy.$Proxy19 

그러므로 항상 ge @Component 콩이 싱글 톤 범위 임에도 불구하고 다른 HttpServletRequest 개체를 지정합니다. 당신이 WebApplicationContent를 인스턴스화 할 때, 기본 BeanFactory 일부 유형을 해결하기위한 몇 가지 특별한 ObjectFactory 인스턴스를 등록

:


다음은 설명입니다. 이는 WebApplicationContextUtils.registerWebApplicationScopes(..)에서 이루어집니다. 이 중 하나는 봄이 당신의 bean을 검색하고 필드 (ServletRequest의 하위 유형)을 HttpServletRequest, 그것은 분해 종속성의지도에서보고이를 얻을 것이다 autowire하기 위해 필요하다고 판단하면

beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory()); 

다음 RequestObjectFactory.

이것은 ObjectFactory이고 주입 대상이 인터페이스 유형이므로 Spring은 각 요청에 대해 RequestObjectFactory에 의해 생성/반환 된 객체에 위임하는 해당 유형의 프록시를 만듭니다. 이것은 AutowireUtils.resolveAutowiringValue(..)에서 이루어집니다.

이와 같이, Foo 빈은 요청 범위가 될 필요가 없습니다.

1

스프링은 프록시를 사용합니다. 그렇습니다. Spring은 싱글 톤에 프록시를 삽입하여 싱글 톤 범위의 객체에 요청 또는 세션 범위의 객체를 삽입 할 수있게합니다.

스프링 MVC의 경우, 주입 된 프록시는 각 요청이 스레드에 바인드되어 있기 때문에 ThreadLocal 변수로 뒷받침된다고 생각합니다. 실제 HttpServletRequest은 호출 될 때 ThreadLocal에 위임 한이 주입 된 프록시를 통해 사용할 수 있습니다.

따라서 "Foo"를 세션 또는 요청 범위로 선언 할 필요가 없으며이를 Singleton으로 유지할 수 있습니다.