无法理解spring-mvc的`@Autowired HttpServletRequest`

Fre*_*ind 5 spring httprequest autowired spring-bean

在我们的spring应用程序中,我们HttpServletRequest以两种方式使用:

(这里的代码简洁,似乎毫无意义)

  1. 在控制器中:

    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<String> hello(HttpServletRequest request) {
        System.out.println("## controller req.hashcode: " + request.hashCode());
        System.out.println("## header 'abc': " + request.getHeader("abc"));
        return new ResponseEntity<String>("OK", HttpStatus.OK);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在正常组件中:

    @Component
    class RequestService {
        private final HttpServletRequest request;
        @Autowired
        public RequestService(HttpServletRequest request) {
            this.request = request;
        }
        public String getHeaderAbc() {
            System.out.println("## service req.hashcode: " + request.hashCode());
            return this.request.getHeader("abc");
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

起初,我认为第二种方式是完全错误的,因为它应该只注入request一次实例.因此,无论何时调用getHeaderAbc()方法,它都应返回相同的值(第一个请求).

但是当我尝试它时,我发现了一些有趣的东西:

  1. request.hashCode()控制器中始终是不同的(如我所料)
  2. request.hashCode()RequestService始终是相同的(我认为)
  3. 但是如果我用不同的abc头发出请求,则标头值会有所不同!

对于单身人士来说RequestService,spring保留了request实例,但更改了它包含的标题!

怎么理解呢?

Evg*_*rov 8

看一下范围代理.http://www.java-allandsundry.com/2012/08/spring-scoped-proxy.html 基本上你注入了一个代理,它保留对当前HttpRequest bean的引用,并为你提供正确的代理,通过请求id选择它.

恕我直言,在Web层之外使用HttpRequest不是一个好习惯.我只会在控制者中使用它.