【问题标题】:Spring scopes behaviour with respective to single and multiple web request/sessionSpring作用域行为与单个和多个Web请求/会话相关
【发布时间】:2017-08-02 13:39:36
【问题描述】:

每当我尝试分析以了解弹簧范围时,我都会卡在某个地方。以下是我对分析的理解,在得出结论之前,我想与您确认一下。如果我的理解有误,请纠正我。

<bean id="signupController" class="com.crp.controller.SignupController"
        scope="">

如果范围是“请求”,那么对于来自客户端的每个新请求,无论会话如何,spring 容器都会生成新实例。一旦请求完成,spring容器将设法关闭实例的生命周期。

如果范围是“会话”,那么对于会话的第一个请求,spring 容器将生成一个新实例,并为该特定会话的所有客户端请求维护它。一旦会话超时,spring 容器将设法关闭实例的生命周期。

如果范围是“原型”,则无论会话如何,只要请求 bean,spring 容器都会生成新实例。开发者应该管理实例的生命周期,因为 Spring 容器不会管理原型范围的生命周期。

如果范围是“单例”,则只有一个实例由 spring 容器生成并保持它可用于所有请求,而与会话无关。对于每个会话,都会维护一个单例实例的副本,以便一个会话单例对象不会被另一个会话共享,并且 Spring 容器将管理单例实例副本的生命周期并在会话超时时将其关闭。

注意:我相信你们中的大多数人可能对我对单例范围的理解有不同的看法。甚至我也对单例范围的行为感到困惑,并在分析过程中获得不同的信息。请分享你的想法

谢谢。

对于单例范围,容器如何在以下实现中为多个用户(会话)同时发送请求。

登录.java:

public class Login {
    private String username;
    private String password;

    public String getUsername() {
    return username;
    }

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

    public String getPassword() {
    return password;
    }

    public void setPassword(String password) {
    this.password = password;
    }
}

LoginController.java:

public class LoginController extends MultiActionController {

    private Login login;

    public ModelAndView submitLogin(HttpServletRequest request,
        HttpServletResponse response) {
    String userName = request.getParameter("username");
    String password= request.getParameter("password");
    getLogin().setUserName(userName);
    getLogin().setPassword(password);
    // TODO send login bean to DAO for executing further business logic.
    }

    public Login getLogin() {
    return login;
    }

    public void setLogin(Login login) {
    this.login = login;
    }
}

context.xml:

<bean id="login" class="com.crp.bean.Login" scope="singleton">
</bean>

<bean id="loginController" class="com.crp.controller.LoginController" scope="singleton">
        <property name="login" ref="login"></property>
</bean>

【问题讨论】:

    标签: spring spring-mvc


    【解决方案1】:

    不,这并不完全正确。

    如果范围是“请求”,那么对于来自客户端的每个新请求,无论会话如何,spring 容器都会生成新实例。

    没有。只有当代码调用 bean 上的方法(即在包装实际 bean 实例的作用域代理上)时,才会创建 bean 实例。但是你是对的,每个请求都有一个与其他请求不同的 bean 实例,并且 bean 在请求结束时被销毁(即它的生命周期钩子,如果它们存在,则在请求结束时调用)。

    如果范围是“会话”,那么对于会话的第一个请求,spring 容器将生成一个新实例,并为该特定会话的所有客户端请求维护它。

    与请求范围的备注相同:bean 实例是按需创建的。

    如果作用域是“原型”,则无论会话如何,只要请求 bean,spring 容器都会生成新实例。

    没错。但请注意,您需要向 spring 上下文请求一个 bean 实例才能获取一个新实例。如果您将原型注入到单例 bean,则单例 bean 将在其整个生命周期中保持对该 bean 的引用,因此每次单例 bean 调用它时都会使用相同的原型 bean。

    如果范围是“单例”,则只有一个实例由 spring 容器生成并保持它可用于所有请求,而与会话无关。对于每个会话,都会维护一个单例实例的副本,以便一个会话单例对象不会被另一个会话共享,并且 Spring 容器将管理单例实例副本的生命周期并在会话超时时将其关闭。

    没有。那是完全错误的。根本没有复制。一个实例被创建,到处注入,并在任何地方同时使用。 bean 仅在应用程序本身结束时被销毁。

    【讨论】:

    • @JB Nizet - 非常感谢,我很清楚其他单例范围,假设当多个会话(用户)同时请求访问登录 bean 并提交用户名和密码,现在容器将如何处理这种情况,单例 bean 是否会覆盖每个会话请求并维护最后一个会话用户名和密码,或者它将如何工作?否则我不应该将登录 bean 定义为单例?
    • 我不确定我理解你的意思。假设您的 bean 在单例 bean LoginBean 中有一个方法 login(HttpServletRequest request),那么多个线程将在同一个唯一的 LoginBean 实例上同时调用此方法,但每个线程将使用自己的请求。这说明清楚了吗?如果没有,请编辑您的问题,并添加您希望澄清的代码示例。
    • 我在帖子中添加了我的场景代码,我知道我实现的方式很可悲,但我需要正确理解概念。
    • 这个实现确实是不正确的:每个并发请求都会修改相同的、唯一的登录 bean。如果登录 bean 具有请求范围,那将是正确的。但这甚至不应该是春豆。您应该在 submitLogin() 方法中使用 new 创建一个实例。
    • 好的,我理解我的错误(弹簧功能的过度/错误使用)。
    猜你喜欢
    • 2011-06-15
    • 2016-01-18
    • 1970-01-01
    • 2017-04-13
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多