If somewhere I have a singleton @Component bean "Foo" with a @Autowired HttpSession or HttpServletRequest, does Foo itself have to be declared session (or request) scoped, or can I just keep it as a simple singleton --- in which case HttpSession and/or HttpServletRequest are probably already injected as scoped proxies anyway via Spring?
Here's a pretty simple test to check behavior (Spring 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;
}
and
@Component
public class Foo {
@Autowired
public HttpServletRequest request;
}
If you send a request, you'll note that the attribute returned is always null and that the class is something like
class com.sun.proxy.$Proxy19
Therefore you are always getting a different HttpServletRequest object even though the @Component bean is singleton scoped.
Here's the explanation:
When you instantiate a WebApplicationContent, it registers some special ObjectFactory instances for resolving some web types in the underlying BeanFactory. This is done in WebApplicationContextUtils.registerWebApplicationScopes(..). One of these is the following
beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
When Spring scans your beans and determines that it needs to autowire the HttpServletRequest (which is a sub type of ServletRequest) field, it will look in its map of resolvable dependencies and get this RequestObjectFactory.
Because this is an ObjectFactory and the injection target is an interface type, Spring will create a Proxy of that type that delegates to the object created/returned by the RequestObjectFactory on each request. This is done in AutowireUtils.resolveAutowiringValue(..).
As such, your Foo bean does not need to be request scoped.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With