• Bean的作用域和生命周期


    变量的作用域
    变量的作用域是指一个变量生效的范围,作用的范围。比如定义了一个类变量,就意味着类里面的所有方法都可以使用;如果变量定义在方法里面,就称为方法变量,方法变量只能在方法里面去使用。

    Bean的作用域

    Bean是Spring里面存储的对象,Bean的作用域指的是Bean对象在Spring容器里面的行为
    下面我们用一个例子来看Bean作用域问题:

    • 我们先创建一个公共类Users,调用getUser()方法可以或得一个公共的User对象,我们设置这个公共类的User的id为222,User的name为李四:
    package com.java.demo.model;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.stereotype.Component;
    // 公共类
    @Component
    public class Users {
        @Bean("user")
        public  User getUser(){
             User user=new User();
             user.setId(222);
             getUser().setName("李四");
             return  user;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 假设有两个人需要对这个公共类进行改进,在这里我们用UserController2和UserController3来代表这两个人。
    • UserController2对公共对象的操作如下:
    import com.java.demo.model.User;
    import com.java.demo.model.Users;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    
    @Controller
    public class UserController2 {
        @Autowired
        private User user;
        public  void doMethod(){
            User  user2=user;
            System.out.println("UserController2修改之前"+user);
            user2.setName("张三");
            user2.setId(1111);
            System.out.println("UserController2修改之前:"+user);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    UserController2先定义了一个User类型的变量user2然后将user给user2,然后打印了一下修改之前的user,接着对user2进行id设置和name设置,最后打印一下修改后的user。
    在这里插入图片描述可以看到,公共对象user已经被修改了,id和name都被UserController2进行了修改。虽然UserController2是对user2进行了操作,可是还是改变了原本的user。
    我们再看一下 UserController3:

    package com.java.demo.controller;
    
    import com.java.demo.model.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.stereotype.Controller;
    
    @Controller
    public class UserController3 {
        @Autowired
        private User user;
        public void doMethod(){
            System.out.println("UserController3 的user:"+user);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    UserController3并没有对公共对象user进行任和操作,只是在doMethod方法里面打印了一下公共对象user。UserController3希望拿到的user是没有被改动的user,那我们来看一下代码执行的结果(我们在main方法里面,先调用UserController2的doMethod方法,再调用UserController3的doMethod方法):
    在这里插入图片描述代码执行结果:
    在这里插入图片描述
    结果发现,虽然UserController2重新定义了一个变量,然后进行修改,但是原来的公共对象依旧被改动了,导致UserController3拿到的公共对象user已经是被改动后的了。
    导致这样结果的原因就是:

      private User user;
       User  user2=user;
    
    • 1
    • 2

    这里代码实际上定义一个User类型的变量,这个变量指向的是user对象,并没有新的对象。这时候使用user2去修改对象的时候,就相当于修改了user对象。
    归根结底导致这个问题的原因就是Bean的作用域,Bean对象默认的是单例模式。(单例模式是指在程序的运行期间只有一份)。

    • 如何避免默认单例模式带来的问题?
      手动设置,通过@Scope注解,如@Scope(“prototype”)、prototype就是原型模式:
    package com.java.demo.model;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    // 公共类
    @Component
    public class Users {
        @Bean
        @Scope("prototype")
        public  User getUser(){
             User user=new User();
             user.setId(222);
            user.setName("李四");
             return  user;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述

    Bean作用域类型:
    概念:Bean作用域指的是Bean在Spring容器中的某种行为,比如单例模式,比如原型模式等。

    1. singleton:单例作用域(默认的作用域)
      补充问题:单例模式的Bean是线程安全的吗?不是,因为所有人都可以操作这个公共变量,所以不是线程安全的,使用ThreadLocal可以变成线程安全的。
    2. prototype:原型作用域(多例模式)
    3. request:请求作用域,只适用于Spring MVC项目(就是Spring Web项目)
    4. session:回话作用域,一个Http会话共享一个Bean,是适用于Spring MVC项目。
    5. application:全局作用域,表示的是一个Context容器共享一个作用域。只适用于Spring MVC项目。
    6. websocket:Http WebSocket作用域,只适用于Webscoket作用域。

    Spring的生命周期

    1. 启动容器
    2. 读取配置文件,进行Bean的实例化
    3. 将Bean加入到容器中
    4. 装配Bean属性(给当前类的属性赋值)

    Bean的生命周期

    1. 实例化(内存空间的分配)
    2. 设置Bean属性(进行依赖注入,将依赖的Bean赋值到当前类的属性上)
    3. Bean的初始化
      3.1 执行各种通知
      3.2 初始化的前置方法
      3.3 初始化方法
      3.4 初始化的后置方法
    4. 使用Bean
    5. 销毁Bean
  • 相关阅读:
    基于ESP32的空气质量传感器实现与应用——详解OpenAirProject空气质量/粉尘计
    DTSE Tech Talk丨第3期:解密数据隔离方案,让SaaS应用开发更轻松
    182.Hive(四):企业级调优:执行计划,fetch抓取,本地模式,表的优化,案例实操
    Python 基于docker部署的Mysql备份查询脚本
    Jsp+Servlet+Mysql实现的高校学生社团管理系统
    一个简单的查询学生信息的接口测试
    容器基础镜像的编写及最佳实践
    TinyEngine 开源低代码引擎首次直播答疑Q&A合集
    【刷题心得】双指针法|HashSet<T>
    韩国锂电池工厂火灾:行业安全警钟再次敲响
  • 原文地址:https://blog.csdn.net/laly123321/article/details/132854692