Java面试题-Controller是单例吗,线程安全吗

2021-07-02 11:29:44  晓掌柜  版权声明:本文为站长原创文章,转载请写明出处


一、前言

    Spring的Controller是单例还是多例?是线程安全的吗?怎么保证其线程安全?

    上面这个算是在面试中的老生常谈的问题了,今天我们就围绕这个问题,做一个全面的解析。

二、结论

    2.1、是单例吗

        Spring的Controller是单例的。我们可以通过下面的代码进行验证,

        我们不管调用test接口多少次,创建实例这部分的控制台输出都是只有一次的。


/**
* @author XA
* date 2021/7/2 9:57
* description: 测试类controller
*/
@RestController
@Api(tags = "测试")
public class TestController {

private Integer i = 0;

private TestController(){
System.out.println("创建实例...");
}

@ApiOperation("test1")
@GetMapping("xaTest1")
public Integer xaTest1(){
System.out.println(++i);
return i;
}

@ApiOperation("test2")
@GetMapping("xaTest2")
public Integer xaTest2(){
System.out.println(++i);
return i;
}

@ApiOperation("test3")
@GetMapping("xaTest3")
public boolean xaTest3(){
System.out.println(++i);
return i%2 == 0;
}

}

    2.2、不是线程安全的

        我们通过postMan或者swagger调用测试发现,首次请求test1时返回的是1,再次调用test2时返回的是2。

    两次的结果是不一致的,说明不是线程安全的! 

        

    2.3、如何保证线程安全

        这时候我们需要引入一个注解:@Scope("prototype")        

            

        然后我们在重复上述操作可以发现,两次的请求是一致的了        

        

三、分析

    3.1、为什么是单例

        为了性能:不需要在每次使用时都new一个,减少资源消耗

    3.2、如何保证线程安全

        ① 不在controller中定义成员变量

        ② 不得不定义成员变量时,使用@Scope("prototype")声明为多例

    3.3、关于@Scope("prototype")注解

        ① 单例模式下,Spring会初始化所有作用域下的Bean并统一管理。

        ② 配置了@Scope("prototype")后,有单例变成了原型模式,每次通过getBean时都会产生一个新的实例,

           这时的Bean不再由Spring统一管理

    PS: 通过下图我们也可以看到,配置了@Scope("prototype")后,每次请求都会创建一个实例的

    

    更多精彩请持续关注:guangmuhua.com


最新评论: