Spring中Bean的作用域问题


一、通过案例来简单体会一下Bean的作用域问题

User:


public class User {
    private String name;
    public User() {
        System.out.println("加载User");
    }
    public String sayHi() {
        return "Hello Dada!";
    }
}

🧡注意:
@DataLombok注解,作用大家可以自行了解一下,使用这个注解可以省去实体类中大量的get()set()toString()等方法。

公共Bean:


public class UserBean {
    
    public User user() {
        User user = new User();
        user.setName("哒哒");
        System.out.println("Bean原名:" + user.getName());
        return user;
    }
}

第一个用户使用公共Bean时,进行了修改操作:


public class ModifyUser {
    
    private User user1;

    public User getUser() {
        User user = user1;
        user.setName("阿巴阿巴");
        return user;
    }
}

第二个用户使用公共Bean时:


public class ReferUser {
    
    private User user1;
    public User getUser() {
        User user = user1;
        return user;
    }
}

打印第一个用户和第二个用户公共 Bean 的值:

public class Demo2 {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        ModifyUser modifyUser = context.getBean("modifyUser",ModifyUser.class);
        System.out.println("第一位用户修改user: " + modifyUser.getUser());

        ReferUser referUser = context.getBean("referUser",ReferUser.class);
        System.out.println("第二位用户就是看看user: " +referUser.getUser());
    }

结果:
在这里插入图片描述

可以看见,原来Username是"哒哒",现在是"阿巴阿巴",公共Bean的值发生了改变。

原因有两点:

  1. ModifyUsergetUser()表面创建了一个新的UserUser user = user1;)但只是把user指向了user1实际上修改的还是公共Bean
  2. Bean默认状态下是单例状态(singleton),也就是全局只有这一个Bean,所有人用的都是这一个对象,不再创建新的对象,因为使用单例可以很大程度上提高性能,所以在Spring中,Bean的作用域默认也是singleton单例模式。

在这里插入图片描述

二、作用域定义

这是我们之前对于作用域的理解:

限定程序中变量的可用范围叫做作用域,或者说在源码中定义变量的某个区域就叫做作用域。

Bean的作用域是指BeanSpring整个框架中的某种行为模式,比如singleton单例作用域,就表示Bean在整个Spirng中只有一份,它是全局共享的,如果别人修改了这个Bean,另外的人读到的就是被修改的Bean了。

那么Bean的作用域也不单单只有singleton单例作用域这一种。

三、Bean的作用域分类

singleton

  • 描述: singleton作用域下的BeanIoC容器中只存在一个实例: 获取Bean(使用applicationContext.getBean等方法获取)及装配Bean(使用@Autowired@Resource)都是同一个对象。
  • 场景: 通常是当所有人调用这个Bean都只是调用,而不是修改时,就使用singleton(通常是无状态的Bean使用该作用域。)
  • Spring默认使用该作用域

prototype

原型模式(多例模式)

通俗的理解就是本身是啥样就是啥样,比如上面的ModifyUser一开始和ReferUser都是拿到它原生的样子,本来等于“哒哒”的样子。

要保证每次都是原生的样子,那每次请求注入这个对象,都会new一个新对象,就是克隆(深克隆)一个原型的对象,所以我每次拿到的都是一个新的对象,要修改就是在这个新对象上进行修改,不会影响我的原型。

  • 描述: 每次对该作用域下的Bean请求都会创建新的实例:获取Bean(使用applicationContext.getBean等方法获取)及装配Bean(使用@Autowired@Resource)都是新的对象实例。
  • 场景: 当有人调用这个Bean会进行修改时,就使用prototype。(通常是有状态的Bean使用该作用域。)

request

请求作用域

  • 描述: 每次http请求都会创建新的Bean实例,类似于prototype
  • 场景: 一次http请求和响应共享一个Bean,来回的过程这个Bean共享
  • 限定在SpringMVC中使用,就是SpringWeb项目。

类似于Servlet,在Servlet上进行了封装。当使用ajax或使用浏览器时,访问一个地址,可以直接触发到程序里的某一个方法。

session

会话作用域

  • 描述: 在一个http session中,定义一个Bean实例
  • 场景: 用户会话的共享Bean,比如记录一个用户的登录信息
  • 限定SpringMVC中使用

比如我登陆了一个账号,那就是一次会话请求。
然后在整个操作期间,比如使用了30min,使用的都是一个账号,那么这个Bean在我的会话当中是一直共享的,此时另一个人登了另外账号,那么这个另外的账号和我的账号在逻辑上就是隔离的,不能相互共享的。每个会话都有自己的Bean
跟多线程中的ThreadLocal(每个线程都会有自己的变量)比较像。

application(了解)

全局作用域

  • 描述:在一个http servlet Context中,定义一个Bean实例
  • 场景:Web应用的上下文信息,比如,记录一个应用的共享信息
  • 备注:限定SpringMVC中使用

如:

ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

这一个ApplicationContext就是一个http servlet对象,如果此时我又新new了一个ApplicationContext,那么这两个对象信息就是不共享的,但一个ApplicationContext里面的信息是共享的。

singleton(单例作用域) 和 application (全局作用域)的区别

  1. 本身的应用范围是不一样的, singleton应用在Spring Core里面, application应用在SpringMVC里面
  2. singleton作用于IoC容器,而application作用于Servlet容器

websocket(了解)

socket通讯是应用层的协议,底层可以通过TCP通讯,也可以通过UDP通讯

  • 描述: 在一个HTTP WevSocket的声明周期中,定义一个Bean实例
  • 场景: WebSocket的每次会话中,保存了一个Map结构的头信息,将用来包裹客户端消息头。第一次初始化后,直到WebSocket结束都是同一个Bean
  • Spring WebSocket中使用

四、Bean作用域设置

设置成原型模式:

  1. 通过全局变量设置: @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  2. 直接通过值设置: @Scope("prototype")

在存Bean对象的时候,在Bean上加作用域。
在这里插入图片描述
在这里插入图片描述

总结

在这里插入图片描述

你可以叫我哒哒呀
本篇到此结束
“莫愁千里路,自有到来风。”
我们顶峰相见!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值