Java 在SpringMVC中,控制器是单例的,为什么我的代码是线程安全的?(AutowiredHttpServeltRequest)

Java 在SpringMVC中,控制器是单例的,为什么我的代码是线程安全的?(AutowiredHttpServeltRequest),java,spring,multithreading,spring-mvc,servlets,Java,Spring,Multithreading,Spring Mvc,Servlets,这对我来说很奇怪。 我有以下代码: @Controller public class MyTestController { @Autowired private HttpServletRequest request; @RequestMapping("/print/") public String PrintInfo() throws Exception { Thread.sleep(5000); System.out.prin

这对我来说很奇怪。 我有以下代码:

@Controller
public class MyTestController {
    @Autowired
    private HttpServletRequest request;

    @RequestMapping("/print/")
    public String PrintInfo() throws Exception {

        Thread.sleep(5000);
        System.out.println("name:" +request.getParameter("name"));
        System.out.println("hashcode:" +request.hashCode());

        return "testpage";
    }
}
我同时访问了以下url:

http://127.0.0.1:8080/MyApp/print/?name=tom
http://127.0.0.1:8080/MyApp/print/?name=mike
它印刷了:

 name:tom
 hashcode:2006506443
 name:mike
 hashcode:2006506443
MyTestController是singleton。请求的哈希代码相同,这意味着不同的请求具有相同的实例

但是为什么
request.getParameter(“name”)
会给出正确的结果呢? 也许getParameter方法只是一个需要从其他对象读取数据的方法


我不知道,这让我很困惑。有人可以解释吗?

我说您的MyTestController是单例的,但是实现HttpServletRequest的类不是

每次收到请求时,底层服务器中的servlet容器将为类创建一个新实例,该类为HttpServletRequest接口提供了实现,然后该对象的引用将传递给MyTestController

这就像每次调用时向一个方法传递不同的参数一样。

摘录应该可以回答您的问题:

作为依赖项的作用域bean

SpringIOC容器不仅管理 对象(bean),以及协作者(或 依赖项)。如果希望注入(例如)HTTP请求 将作用域bean放入寿命更长的作用域的另一个bean,您可以选择 插入AOP代理来代替作用域bean。也就是说,你需要 插入一个代理对象,该代理对象公开与 作用域对象,但也可以从 相关作用域(如HTTP请求)和委托方法调用 在真实的物体上

请求范围基于中的线程本地属性(默认情况下由
DispatcherServlet
为每个请求初始化)

因此,您的
HttpServletRequest
是一个动态JDK代理,它在每次方法调用时都会检查线程本地属性,以获取真正的请求对象并调用它

可解析请求依赖项本身被注册为bean,作为
WebApplicationContext
初始化的一部分

这里是一个稍微简化的图表(图中的所有内容实际上都是单例):


打印您请求的类别。。。它可能是一个JDK代理,它能够从正确的作用域中拉出依赖项(通过
RequestContextHolder
上的本地线程保持)。我认为Spring文档中有一章专门介绍了这一点……神奇之处。我说这是一种邪恶的魔法:)聪明的把戏破坏了我们对物体的常识。谢谢。根据你的回答,它需要一些配置。但我还没有配置任何AOP代理。那么这些神奇的事情是怎么发生的呢?不。。。这是开箱即用的东西。Spring为默认场景进行了大量的自动配置。我只是在彻底解释“幕后”正在发生的事情。您可以通过放置断点并检查堆栈跟踪来验证这一点(请这样做-这是理解任何框架的内部工作的最佳方式)。