zoukankan      html  css  js  c++  java
  • SpringMVC的Controller是单例还是多例?

    声明

    文章参考:https://blog.51cto.com/lavasoft/1394669

    https://blog.csdn.net/qq_27026603/article/details/67953879

    https://www.cnblogs.com/nangonghui/p/8988647.html

    正文

    Spring MVC Controller默认是单例的:

    单例的原因有二:

    1、为了性能。

    2、不需要多例。

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

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

      我这里说不需要的原因是看开发者怎么用了,如果你给controller中定义很多的属性,那么单例肯定会出现竞争访问了。

      因此,只要controller中不定义属性,那么单例完全是安全的。下面给个例子说明下:

    package com.xgcd.scope;
    
    import org.springframework.context.annotation.Scope;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    //@Scope(value = "prototype")
    @RequestMapping("/mvcController")
    public class SpringMvcControllerScope {
        private static int st = 0;// 静态的
        private int index = 0;// 非静态的
    
        @RequestMapping("/test")
        public String test() {
            System.out.println(st++ + "|" + index++);
            return "index";
        }
    
    }

    1/当scope="prototype"时, 原型模式, 多例, 多次请求(集成了oauth2)

    http://localhost:8080/mvcController/test?access_token=9f041ad8-d146-455d-a7ec-7a473f6ae463

    控制台结果:

    0|0
    1|0
    2|0
    3|0
    4|0
    5|0
    6|0
    ...

    2/把@Scope注解注释掉, 则默认是单例, 多次请求

    http://localhost:8080/mvcController/test?access_token=4a0e8345-dd38-4d7a-82f2-5681299e8f07

    控制台结果:

    0|0
    1|1
    2|2
    3|3
    4|4
    5|5
    6|6
    ...

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

    最佳实践:

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

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

    扩展

    当面试官问springmvc和struts2的区别的时候, 也可以从这一点出发, 我想他要考察的点也在于此?

    尽量不要在controller里面去定义属性,如果在特殊情况需要定义属性的时候,那么就在类上面加上注解@Scope("prototype")改为多例的模式。

    以前struts是基于类的属性进行发的,定义属性可以整个类通用,所以默认是多例,不然多线程访问肯定是共用类里面的属性值的,肯定是不安全的。

    但是springmvc是基于方法的开发,都是用形参接收值,一个方法结束参数就销毁了,多线程访问都会有一块内存空间产生,里面的参数也是不会共用的,所有springmvc默认使用了单例,所以controller里面不适合在类里面定义属性,只要controller中不定义属性,那么单例完全是安全的。

    springmvc这样设计主要的原因也是为了提高程序的性能和以后程序的维护只针对业务的维护就行,要是struts的属性定义多了,都不知道哪个方法用了这个属性,对以后程序的维护还是很麻烦的。

    如何解决单例模式下线程不安全的问题?

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

  • 相关阅读:
    SpringBoot整合redis
    maven dependency全局排除
    Spring Boot程序接收命令行参数
    MySQL8.0.20安装详解
    ITRS/GCRS/J2000坐标系的相互转换
    SpringBoot日记——日志框架篇
    SpringBoot集成log4j,解决log4j.properties不生效问题
    Office
    git下载
    WINDOWS上KAFKA运行环境安装
  • 原文地址:https://www.cnblogs.com/yadongliang/p/13049543.html
Copyright © 2011-2022 走看看