zoukankan      html  css  js  c++  java
  • Spring的Controller是单例还是多例?怎么保证并发的安全

    答案:

     

    controller默认是单例的,不要使用非静态的成员变量,否则会发生数据逻辑混乱。正因为单例所以不是线程安全的。

    我们下面来简单的验证下:

     

    package com.riemann.springbootdemo.controller;

    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;

    /**
     * @author riemann
     * @date 2019/07/29 22:56
     */
    @Controller
    public class ScopeTestController {

        private int num = 0;

        @RequestMapping("/testScope")
        public void testScope() {
            System.out.println(++num);
        }

        @RequestMapping("/testScope2")
        public void testScope2() {
            System.out.println(++num);
        }

    }

     

    我们首先访问 http://localhost:8080/testScope,得到的答案是1;

    然后我们再访问 http://localhost:8080/testScope2,得到的答案是 2。

     

    得到的不同的值,这是线程不安全的。

    接下来我们再来给controller增加作用多例 @Scope("prototype")

     

    package com.riemann.springbootdemo.controller;

    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;

    /**
     * @author riemann
     * @date 2019/07/29 22:56
     */
    @Controller
    @Scope("prototype")
    public class ScopeTestController {

        private int num = 0;

        @RequestMapping("/testScope")
        public void testScope() {
            System.out.println(++num);
        }

        @RequestMapping("/testScope2")
        public void testScope2() {
            System.out.println(++num);
        }

    }

     

    我们依旧首先访问 http://localhost:8080/testScope,得到的答案是1;

     

    然后我们再访问 http://localhost:8080/testScope2,得到的答案还是 1。

     

    相信大家不难发现 :

     

    单例是不安全的,会导致属性重复使用。

    解决方案

    • 不要在controller中定义成员变量。

    • 万一必须要定义一个非静态成员变量时候,则通过注解@Scope(“prototype”),将其设置为多例模式。

    • 在Controller中使用ThreadLocal变量

    补充说明

    spring bean作用域有以下5个:

     

    singleton: 单例模式,当spring创建applicationContext容器的时候,spring会欲初始化所有的该作用域实例,加上lazy-init就可以避免预处理;

     

    prototype: 原型模式,每次通过getBean获取该bean就会新产生一个实例,创建后spring将不再对其管理;

     

    (下面是在web项目下才用到的)

     

    request: 搞web的大家都应该明白request的域了吧,就是每次请求都新产生一个实例,和prototype不同就是创建后,接下来的管理,spring依然在监听;

     

    session: 每次会话,同上;

     

    global session: 全局的web域,类似于servlet中的application。

  • 相关阅读:
    VC 常见问题百问
    python windows 环境变量
    Check server headers and verify HTTP Status Codes
    Where are the AES 256bit cipher suites? Please someone help
    outlook 如何预订会议和会议室
    安装Axis2的eclipse插件后,未出现界面
    windows 环境变量
    python 时间日期处理汇集
    openldap学习笔记(使用openldap2.3.32)
    set p4 environment in windows
  • 原文地址:https://www.cnblogs.com/taleche/p/13494387.html
Copyright © 2011-2022 走看看