zoukankan      html  css  js  c++  java
  • Spring的Controller默认是单例还是多例

      Spring bean作用域

      先看看spring的bean作用域有几种,它们之间分别有啥不同。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。 

      好了,上面都说了Spring的controller默认是单例,那很自然就是singleton了。 

      再通过一个例子看看单例会不会有如下问题——类中定义的非静态变量线程安全问题。为什么Spring要默认是单例呢?原因有二:

      1、为了性能。这个不用废话了,单例不用每次都new,当然快了。

      2、不需要多例。不需要多实例会让很多人迷惑,因为Spring MVC官方也没明确说不可以多例。

      我这里说不需要的原因是看开发者怎么用了,开发者如果在controller中定义很多的属性,那么单例肯定会出现竞争访问了。因此,只要controller中不定义属性,那么单例完全是安全的。下面给个例子说明下:

    import org.springframework.context.annotation.Scope;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    @RequestMapping("/scopeTest")
    // @Scope("prototype")
    public class ScopeTestController {
    
        private int num = 0; //非静态成员变量
    
        @RequestMapping("/testScope")
        public void testScope() {
            System.out.println("testScope --> " + ++num);
        }
    
        @RequestMapping("/testScope2")
        public void testScope2() {
            System.out.println("testScope2 --> " + ++num);
        }
    }

      依次请求testScope()和testScope2()函数,执行结果是

    testScope --> 1
    testScope2 --> 2

      改为多例,即去掉@Scope("prototype")前面的注释,则执行结果是

    testScope --> 1
    testScope2 --> 1

      相信大家不难发现 :单例是线程不安全的,会导致属性重复使用。如果把num定义为类变量,无论是否使用多例模式,都会复用类变量,感兴趣的小伙伴可以验证一下。解决方案:

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

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

      3、在controller中使用ThreadLocal变量。

    Reference

     https://www.cnblogs.com/zxf330301/articles/6105127.html


      读后有收获,小礼物走一走,请作者喝咖啡。

    赞赏支持

  • 相关阅读:
    利用dockerfile定制镜像
    发布Docker 镜像到dockerhub
    Docker 停止容器
    133. Clone Graph
    132. Palindrome Partitioning II
    131. Palindrome Partitioning
    130. Surrounded Regions
    129. Sum Root to Leaf Numbers
    128. Longest Consecutive Sequence
    127. Word Ladder
  • 原文地址:https://www.cnblogs.com/east7/p/13591892.html
Copyright © 2011-2022 走看看