• Spring中Bean的作用域


    目录

    一、什么是Bean的作用域

    二、@Scope注解

    三、Bean的6种作用域

    3.1 singleton单例模式

    3.2 prototype 原型模式

    3.3 request

    3.4 session

    3.5 application

    3.6 websocket


    一、什么是Bean的作用域

    在之前学习的过程中,我们把作用域定义为:限定程序中变量的可用范围,或者说是定义变量的某个区域。但是,在Bean中,这个作用域指的是Bean在Spring框架中的某种行为。接下来以一个案例分析一下

    首先创建一个User类,同时创建一个Users类将User对象储存到Spring中,这里都是利用注解的方式,以后也是采取这种方式了

    1. public class User {
    2. private String name;
    3. private int id;
    4. @Override
    5. public String toString() {
    6. return "User{" +
    7. "name='" + name + '\'' +
    8. ", id=" + id +
    9. '}';
    10. }
    11. public String getName() {
    12. return name;
    13. }
    14. public void setName(String name) {
    15. this.name = name;
    16. }
    17. public int getId() {
    18. return id;
    19. }
    20. public void setId(int id) {
    21. this.id = id;
    22. }
    23. }
    1. @Component
    2. public class Users {
    3. @Bean
    4. public User user() {
    5. User user = new User();
    6. user.setName("公共名");
    7. user.setId(1);
    8. return user;
    9. }
    10. }

    这里有一个需求就是一个开发人员需要获取到这个User类的对象,并将这个User类对象中原始的“公共名”改成张三,并且不能修改原类名!

    在这个操作中,开发人员并没有直接拿user对象去修改其中的属性,而是另外创建了一个user1去接收user同时在user1中对name属性进行修改

    1. @Controller
    2. public class UserController1 {
    3. @Resource
    4. private User user;
    5. public void setName() {
    6. User user1 = user;
    7. user1.setName("张三");
    8. System.out.println(user1);
    9. }
    10. }

    通过在Spring的配置文件中配置注解扫描路径,然后再通过Spring提供的工厂获取到类对象。通过测试我们发现已经是成功了。

    1. @Test
    2. public void test() {
    3. ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
    4. UserController1 userController1 = ctx.getBean("userController1", UserController1.class);
    5. userController1.setName();
    6. }

    按照思路这里应该是没有修改原来的user类的,但是突然有一天另一位开发人员需要去获取原来user类中的内容

    1. @Controller
    2. public class UserController2 {
    3. @Resource
    4. private User user;
    5. public void getUser() {
    6. System.out.println(user);
    7. }
    8. }
    1. public void test() {
    2. ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
    3. // 这里是第一个开发人员的
    4. UserController1 userController1 = ctx.getBean("userController1", UserController1.class);
    5. userController1.setName();
    6. // 第二个开发人员的
    7. UserController2 userController2 = ctx.getBean("userController2", UserController2.class);
    8. userController2.getUser();
    9. }

    这里测试就会发现有问题了,原始类中的name也被修改了,其实这就是我们说的Bean的作用域因为Bean作用域默认是Singleton,所以这里只会创建出一个对象!

     

    二、@Scope注解

    对于上述的问题我们要怎么去解决呢?我们这里引入一个新的注解@Scope来设置Bean的作用域,这里将Bean的作用域设置为“prototype”原型模式(多例模式)

    1. @Component
    2. public class Users {
    3. @Bean("user")
    4. @Scope("prototype")
    5. public User user() {
    6. User user = new User();
    7. user.setName("公共名");
    8. user.setId(1);
    9. return user;
    10. }
    11. }

     再次运行测试程序,我们发现这个问题就解决了

    除了直接写上作用域的方式@Scope还提供了一种添加作用域的方式:使用枚举设置,这种方式和直接写作用域名称的方式是等价的

    1. @Component
    2. public class Users {
    3. @Bean("user")
    4. @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    5. public User user() {
    6. User user = new User();
    7. user.setName("公共名");
    8. user.setId(1);
    9. return user;
    10. }
    11. }

    三、Bean的6种作用域

    3.1 singleton单例模式

    描述:该作用域下的Bean在IoC容器中只有一个实例:获取Bean(即通过
    applicationContext.getBean等⽅法获取)及装配Bean(即通过@Autowired注⼊)都是同⼀个对象

    场景:通常⽆状态的Bean使⽤该作⽤域。⽆状态表示Bean对象的属性状态不需要更新

    备注:Spring默认选择该作用域

    3.2 prototype 原型模式

    描述:每次对该作⽤域下的Bean的请求都会创建新的实例:获取Bean(即通过applicationContext.getBean等⽅法获取)及装配Bean(即通过@Autowired注⼊)都是新的对象实例。
    场景:通常有状态的Bean使⽤该作⽤域

    3.3 request

    描述:每次http请求会创建新的Bean实例,类似于prototype
    场景:⼀次http的请求和响应的共享Bean
    备注:限定SpringMVC中使⽤

    3.4 session

    描述:在⼀个http session中,定义⼀个Bean实例
    场景:⽤户回话的共享Bean, ⽐如:记录⼀个⽤户的登陆信息
    备注:限定SpringMVC中使⽤

    3.5 application

    描述:在⼀个http servlet Context中,定义⼀个Bean实例
    场景:Web应⽤的上下⽂信息,⽐如:记录⼀个应⽤的共享信息
    备注:限定SpringMVC中使⽤

    3.6 websocket

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

  • 相关阅读:
    前台项目第三天(11)
    PyQt5安装以及使用
    Git系列之移动文件
    职场必看!性能测试响应很慢怎么排查?
    Mathorcup数学建模竞赛第四届-【妈妈杯】C题:合理旅游路线的选择与优化(附lingo代码)
    golang:context
    A-Level化学例题解析及练习2
    【无标题】
    OpenAI Chat completion API 入门指南
    vue项目使用canvas画图 实现canvas带背景的橡皮擦 canvas转base64 canvas转file文件方法
  • 原文地址:https://blog.csdn.net/x2656271356/article/details/134063953