Spring 的 Controller 是单例还是多例?怎么保证并发的安全

Java技术迷

共 2950字,需浏览 6分钟

 ·

2021-06-07 15:50


我们经常说单例还是多例,那么究竟他们不同的根源在哪?或者说我们应该从哪一方面具体的去理解了至于这个问题,今天来分享一波

答案:

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 2020/01/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 2020/01/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。

相信大家不难发现 :

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

解决方案

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

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

3、 在Controller中使用ThreadLocal变量

补充说明

SpringBean作用域有以下5个:

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

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

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

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

5、 session:每次会话,同上;


1、Intellij IDEA这样 配置注释模板,让你瞬间高出一个逼格!
2、基于SpringBoot的迷你商城系统,附源码!
3、最牛逼的 Java 日志框架,性能无敌,横扫所有对手!
4、把Redis当作队列来用,真的合适吗?
5、惊呆了,Spring Boot居然这么耗内存!你知道吗?
6、全网最全 Java 日志框架适配方案!还有谁不会?
7、Spring中毒太深,离开Spring我居然连最基本的接口都不会写了

点分享

点收藏

点点赞

点在看

浏览 37
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报