Spring-Controller的范围及其实例变量

时间:2012-06-21 13:44:09

标签: spring spring-mvc

Spring-MVC单例中的所有控制器是否都在不同的会话和请求之间共享?

如果是这样,我假设一个类变量,如

public String name;
所有请求和会话的

都是一样的吗?因此,如果用户X发出请求并且name被设置为 Paul ,则用户Z还将Paul作为属性?

在我的情况下,我不希望这种行为,但想知道是否有更简单,更清晰的OOP方式来获得会话/请求变量session.getAttribute() / request.getAttribute()

2 个答案:

答案 0 :(得分:59)

回答你的第一个问题:是的,Spring MVC控制器默认是单例。对于所有请求和所有会话,将永久共享和显示对象字段。

但是,如果没有任何同步,您可能会遇到各种并发问题(竞争条件,可见性)。因此,您的字段应该volatile(并且private,顺便说一下)修饰符,以避免可见性问题。

回到你的主要问题:在Spring中你可以使用 request - (参见4.5.4.2 Request scope)和 session-scoped (参见:4.5.4.3 Session scope ) 豆子。你可以将它们注入控制器和任何其他bean(甚至是单例!),但是Spring确保每个请求/会话都有一个独立的实例。

将请求和会话范围的bean注入单例时要记住的唯一事情是将它们包装在作用域代理中(例如取自4.5.4.5 Scoped beans as dependencies):

<!-- an HTTP Session-scoped bean exposed as a proxy -->
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session">

    <!-- instructs the container to proxy the surrounding bean -->
    <aop:scoped-proxy/>
</bean>

答案 1 :(得分:8)

是的,Spring-MVC中的控制器是单例。在多个请求之间,您的类变量会被共享,并可能导致歧义。 您可以在控制器上方使用@Scope(“request”)注释来避​​免这种歧义。