Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Spring proxy request attributes?

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?

like image 221
ManRow Avatar asked Sep 16 '26 06:09

ManRow


1 Answers

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.

like image 76
Sotirios Delimanolis Avatar answered Sep 18 '26 23:09

Sotirios Delimanolis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!