混淆了Spring IoC容器和Tomcat

混淆了Spring IoC容器和Tomcat,spring,tomcat,Spring,Tomcat,我开始用SpringMVC开发RESTAPI。 我将它部署在一个Tomcat容器中,它就像一个符咒 由于Tomcat负责为每个请求创建一个新线程(如果我错了,请纠正我),我想知道Spring如何处理这个问题来管理IoC(控制反转)容器 我有以下服务 @Service public class UserService{ private String username; public setUsername(String username){ this.userna

我开始用SpringMVC开发RESTAPI。 我将它部署在一个Tomcat容器中,它就像一个符咒

由于Tomcat负责为每个请求创建一个新线程(如果我错了,请纠正我),我想知道Spring如何处理这个问题来管理IoC(控制反转)容器

我有以下服务

@Service
public class UserService{
    private String username;

    public setUsername(String username){
        this.username = username;
    }

    public getUsername(){
        return this.username;
    }
}
因此,基本上Spring将创建此单例并使其可供所有人使用

如果一个请求出现并设置了“foobar”用户名,那么来自下一个请求(来自不同用户)的“getUsername”调用是否返回“foobar”? Spring是如何处理这种情况的


默认情况下,SpringBean是单实例范围的,这意味着spring创建bean的单个实例,并向所有线程提供相同的实例。因为您的bean是有状态的(username),所以状态也将与所有线程共享,spring在这里没有任何魔力。
因此,如果一个线程设置用户名“xyz”,那么第二个线程会将其视为“xyz”。

就像其他线程提到的那样,默认情况下,Spring会创建单例范围的bean,这样每个线程都会看到与其他线程相同的类级别状态。在这种情况下,最好避免在应用程序中维护类级别的状态,并在方法范围内通过应用程序传递所有必需的数据,从而使它们成为线程安全的

但是,如果需要,Spring允许您为每个线程创建新的bean实例。您可以使用@Scope(“prototype”)注释bean,每个线程将获得一个bean实例。默认值为@Scope(“singleton”)。如果需要,还可以使用其他几个作用域。

来自

只管理一个单例bean的一个共享实例,所有实例 请求具有与该bean定义匹配的一个或多个id的bean 导致Spring返回一个特定的bean实例 容器

换句话说,当您定义bean定义时 springioc容器的作用域是一个单例,它只创建一个单例 由该bean定义定义的对象的实例。这首单曲 实例存储在此类单例bean的缓存中,所有 该命名bean的后续请求和引用返回 缓存对象


无论有多少线程,都只有一个实例。春天一事无成。与state共享单例通常是不应该做的事情。这是否意味着默认情况下我应该将prototype作用域放在服务上?是的,如果您绝对确定每次都需要一个新实例,并且希望在类/对象中维护状态,请使用prototype作用域。对于大量并发线程/用户,您可能会看到更多创建的对象实例对性能的影响。因此,这是一个你需要做出的权衡——在内存中有更多的对象实例,或者重新设计你的应用程序以避免维护对象中的状态,然后恢复到使用单例。