• Spring中Bean的作用域和生命周期


    Bean的作用域

    我们知道传统意义上的作用域就是一个一个变量限定在程序的可用范围或者源代码中某个变量定义的某个区域叫做作用域!
    我们Spring中的Bean作用域并不是传统意义上的定义,Spring下的Bean的作用域指的是一个Bean对象的在Spring下的行为模式,就列如我们知道的单例模式singleton就是Bean的一种作用域!

    Bean的六种作用域

    • singleton 单例作用域(默认)
    • prototype 原型作用域(多例模式)
    • request 请求作用域(SpringMVC)
    • session会话作用域(SpringMVC)
    • application 全局作用域(SpringMVC)
    • websocketHTTP WebSocket作用域(Spring WebSocket)

    singleton单例作用域
    该作用域下的Bean在IoC容器下只存在一个实例!
    所以对该bean进行注入,装配bean都是同一个对象!
    Spring默认作用域

    当我们创建一个Bean注册到Spring中后,如果有2个类需要注入该Bean!一类进行读取操作,另一个类进行修改操作!如果修改操作在前,那另一个类读取的操作就会读到脏数据,本来想读取到的是Bean初始值,结果读取到了另一个类修改后的数据!,这就说明Bean对象在Spring下是共享的,一个bean对象是单例!当注入时,是多个类共享的!

    //创建User Bean对象!
    public class User {
        private String name;
        private int id;
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", id=" + id +
                    '}';
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    //将Bean 注册到Spring中!
    @Component
    public class Users {
        @Bean //将对象注册到spring中!
        public User getUser(){
            User user = new User();
            user.setId(666);
            user.setName("java");
            return user;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    //User1进行读操作!
    @Controller
    public class UserController1 {
        //注入对象!
        @Autowired
        private User user;
        public User getUser() {
            return user;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    //User2进行修改操作!
    @Controller
    public class UserController2 {
        @Autowired //注入对象!
        private User user;
        //将user对象改了!
        public User getUser() {
            user.setName("C++");
            user.setId(999);
            return user;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    //先修改Bean后读取
    //启动类!!!
    public class app {
        public static void main(String[] args) {
            //获取上下文!
            ApplicationContext context =
                    new ClassPathXmlApplicationContext("spring-config.xml");
            //user2把bean对象改了!
            UserController2 userController2 = context.getBean(UserController2.class);
            System.out.println(userController2.getUser());
            //user1正在读取bean! 预期读取结果是 java 666 因为这是bean注册的初始值!
            UserController1 userController1 = context.getBean(UserController1.class);
            System.out.println(userController1.getUser());
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    运行结果
    在这里插入图片描述
    User1读取到的是修改后的Bean!

    Bean在Spring默认的作用域是singleton

    prototype原型作用域(多例作用域)
    Spring中对同一个Bean,进行注入装箱每个类获取到的bean都是一个新的实例对象!
    通常有动态Bean使用该作用域

    request请求作用域
    每一次http请求都会创建一个新的Bean实例.类似于prototype作用域
    一次http请求和响应的共享Bean
    限定于SpringMVC中使用

    session会话作用域
    在一次http session中定义一个Bean实例
    用户会话的共享Bean ,比如通过这个作用域记录一个用户的登入信息!
    限定于SpringMVC中使用

    application全局作用域
    在一个http servlet Context中定义一个Bean实例
    Web应用的上下文信息,例如记录应用的共享信息
    限定于SpringMVC中使用

    WebSocket作用域
    在一次WebSocket生命周期中定义一个Bean
    WebSocket的每次会话中保存了一个Map结构的头信息,用来包裹客户端头,第一次初始化直到WebSocket生命周期结束都是同一个Bean
    限定于SpringMVC中使用

    singleton和application对比

    • singleton是Spring Core的作用域 application是Spring Web的作用域
    • singleton作用于IoC容器,application作用于Servlet容器中

    Bean的生命周期

    Bean的执行流程
    在这里插入图片描述
    Bean对象执行流程

    启动Spring容器 —>实例化Bean(分配内存空间,从无到有) —>
    Bean注册到Spring中(存操作) —>将Bean装配到需要用的类中(取操作)

    Bean生命周期

    所谓的生命周期指的是一个对象从诞生到销毁的整个生命过程,我们把这个过程就叫做一个对象的生命周期。

    Bean 的生命周期分为以下 5 大部分:
    1.实例化 Bean(为 Bean 分配内存空间)
    2.设置属性(Bean 注入和装配)
    3.Bean 初始化

    • 实现了各种 Aware 通知的方法,如 BeanNameAware、BeanFactoryAware、ApplicationContextAware 的接口方法;
    • 执行 BeanPostProcessor 初始化前置方法;
    • 执行 @PostConstruct 初始化方法,依赖注入操作之后被执行;
    • 执行自己指定的 init-method 方法(如果有指定的话);
    • 执行 BeanPostProcessor 初始化后置方法。

    4.使用 Bean
    5.销毁 Bean

    销毁容器的各种方法,如 @PreDestroy、DisposableBean 接口方法、destroy-method。

    执行流程如下图所示
    在这里插入图片描述
    实例化和初始化区别

    实例化和属性设置是 Java 级别的系统“事件”,其操作过程不可人工干预和修改;而初始化是给开发者提供的,可以在实例化之后,类加载完成之前进行自定义“事件”处理。

    简单说就是实例化只是分配了内存空间,并没有进行其他操作!
    而初始化是真正创建了一个实例,给这块空间存放了数据!

    我们拿买房举例理解Bean生命流程

    • 实例化(买了一套房)
    • 设置属性(装修)
    • 初始化(买家电,家具各种初始化)
    • 使用Bean(入住使用房间)
    • 销毁Bean(将房子卖了)

    在这里插入图片描述

  • 相关阅读:
    双周赛116(模拟、贪心、记忆化搜索==> 动态规划、线段树)
    科技云报道:数智化这道升维题,云计算能答好吗?
    程序员找不到工作,先去外包过渡2年?千万别去
    【【萌新的SOC学习之自定义IP核的学习与设计】】
    算法竞赛入门 -- 括号画家
    Oracle Primavera Unifier uDesigner 资产管理器(Asset Manager )
    Docker-minio部署
    Vue3-常用的Composition API(组合API)(上篇)
    INTERSPEECH 2022 | 钉钉蜂鸣鸟音频实验室论文入选国际顶会,创新提出窄带滤波网络架构
    【计算机视觉 | 图像模型】常见的计算机视觉 image model(CNNs & Transformers) 的介绍合集(四)
  • 原文地址:https://blog.csdn.net/weixin_52345071/article/details/126681882