【框架篇】Bean作用域和生命周期

在这里插入图片描述

Bean作用域和生命周期

【框架篇】Bean作用域和生命周期_第1张图片

一,Bean作用域

Bean作用域指的是在Spring框架中,定义了Bean实例的创建和销毁方式,以及可以访问该实例的范围,并决定了每次通过容器获取Bean时返回的是同一个实例还是不同的实例。

1.1,Bean作用域介绍

Spring 容器在初始化一个 Bean的实例时,同时会指定该实例的作用域,Bean作用域有以下6种,分别为:

1,Singleton:单例作用域【Spring 默认作用域】

  • 在整个应用程序中只存在一个Bean实例。
  • Spring容器会在第一次请求该Bean时创建实例。
  • 并在后续每次请求该Bean时,容器都返回并重用同一个实例。

2,Prototype:原型作用域【也称多例作用域】

  • 每次请求该Bean时,容器都创建一个新的实例。
  • 每个实例都有独立的状态,不共享状态。
  • 适用于需要每次请求都获得一个新的对象的场景。

3,Request:请求作用域【限定于Spring MVC 使用】

  • 每个HTTP请求都会创建一个新的Bean实例,该实例仅在当前请求范围内有效。

  • 在同一个请求中,多个组件可以共享同一个Request作用域的Bean。

  • 适用于每个请求需要独立实例的Web应用程序的场景。

4,Session:会话作用域【限定于Spring MVC 使用】

  • 每个HTTP会话(Session)都会创建一个新的Bean实例,该实例会在整个会话期间保持有效。
  • 不同用户的不同会话期间,会有独立的Session作用域Bean。
  • 适用于需要在每个用户会话中使用独立的Bean实例的Web应用程序。

5,Application:全局作用域【限定于Spring MVC 使用】

  • 在整个Web应用程序的生命周期中,只有一个Bean实例。
  • 每次请求该Bean时,都返回同一个实例。
  • 适用于需要在整个Web应用程序中共享数据或状态的情况。

6,Websocket:HTTP WebSocket 作用域【限定于Spring WebSocket 使用】

  • 在⼀个HTTP WebSocket的⽣命周期中,定义⼀个Bean实例。
  • 第⼀次初始化Bean后,直到WebSocket结束都是同⼀个Bean。

1.2,Bean作用域的设置

使用@Scope标签就可以用来声明Bean的作用域,@Scope 标签既可以修饰方法也可以修饰类。

@Scope 有两种设置方式:

1,直接设置值:

@Scope("prototype")

【框架篇】Bean作用域和生命周期_第2张图片

2,使用枚举设置:

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

【框架篇】Bean作用域和生命周期_第3张图片


二,Bean生命周期

2.1,Bean生命周期流程

Bean的生命周期指的是Bean对象由诞生到销毁的过程,可大致分为以下5步:

1,Bean实例化:Spring 容器根据配置或注解创建Bean的实例,为其分配内存空间。

2,属性设置:Spring容器会通过依赖注入【DI】或自动装配【Autowiring】的方式将配置的属性值设置给Bean的对应属性

3,初始化

  • 各种通知:Spring容器会检测Bean是否实现了特定的Aware接口,然后通过这些接口回调方法通知Bean获取相关的信息。
    • 例如BeanNameAwareBeanFactoryAwareApplicationContextAware等接口以获得对应对象的引用。
  • 初始化前置方法:检测所有注册的BeanPostProcessor接口的实现类,并依次调用它们的前置处理方法。
    • 可以通过实现postProcessBeforeInitialization()方法,对Bean进行一些额外的处理或修改。
  • 初始化方法:调用Bean的实际初始化方法,可简单地看作是Bean的构造完成后,进行一些额外的初始化工作的方法。
    • 可以通过XML配置文件的init-method属性、使用@PostConstruct注解或实现InitializingBean接口的afterPropertiesSet()方法来指定初始化方法。
  • 初始化后置方法:会继续调用所有注册的BeanPostProcessor接口的实现类,并依次调用它们的后置处理方法。
    • 可以通过实现postProcessAfterInitialization()方法,对Bean进行任何需要的进一步处理

4,使用Bean:Bean就可以在应用程序中根据业务逻辑调用和操作Bean。

5,销毁Bean

  • 销毁前置方法:在应用程序关闭或手动销毁Bean时,Spring容器会调用Bean的销毁前置方法。
    • 可以通过配置XML文件中的destroy-method属性,或使用@PreDestroy注解来指定特定的方法。
  • 销毁方法:在销毁前置方法之后,Spring容器将调用Bean的销毁方法,这可以将其简单地看作清理资源、释放连接等操作的方法。
    • 通过实现DisposableBean接口的方法,以达到执行清理逻辑的功能。

2.2,Bean生命周期流程图

Bean生命周期基本流程图:

【框架篇】Bean作用域和生命周期_第4张图片


2.3,Bean生命周期流程实现

Bean生命周期流程代码实现:

package com.java.component;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Component
public class BeanComponent implements BeanNameAware, BeanPostProcessor {
    @Override
    public void setBeanName(String s) {
        System.out.println("执行通知 BeanName 【" + s + "】");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean,String beanName){
        System.out.println("do postProcessBeforeInitialization 初始化前置方法!【" + beanName + "】");
        return bean;
    }

    private void myInit(){
        System.out.println("do xml方式初始化");
    }

    @PostConstruct
    private void doPostConstruct(){
        System.out.println("do 注解方式初始化");
    }

    @Override
    public Object postProcessAfterInitialization(Object bean,String beanName){
        System.out.println("do postProcessAfterInitialization 初始化后置方法!【" + beanName + "】");
        return bean;
    }

    public void sayHi(){
        System.out.println("do sayHi()");
    }

    @PreDestroy
    public void doPreDestroy(){
        System.out.println("do 注解方式销毁1");
    }

    public void close(){
        System.out.println("do xml方法销毁");
    }
}

代码实现配置文件:

【框架篇】Bean作用域和生命周期_第5张图片

Bean生命周期流程代码运行结果:

【框架篇】Bean作用域和生命周期_第6张图片


思考:为什么在xml里面配置了init-method和destory-method,打印结果时,init方法就会运行,而destory方法不手动调用就不会运行?

解答:是因为配置文件里设置Bean作用域为多例作用域,在多例作用域里,如果未手动调用destory方法,就不会对Bean进行销毁,

而设置Bean作用域为单例作用域,销毁Spring容器时,会先自动调用destory方法进行对Bean的销毁,然后再对Spring容器进行销毁。

理由:当使用多例作用域时,Spring 容器并不会自动调用 destroy 方法来销毁 Bean 实例。多例作用域的 Bean 生命周期由使用者负责管理,如果需要销毁一个多例 Bean 实例,需要显式地调用 destroy 方法或者手动释放相关资源。而当使用单例作用域时,在销毁Spring 容器时,Spring 会自动调用单例 Bean 的 destroy 方法来进行销毁操作,以确保在应用程序关闭时正确地释放资源。

需要注意的是,destroy 方法只针对单个 Bean 进行销毁操作。对于多例模式,如果存在多个实例,需要手动进行销毁操作,先销毁所有的 Bean 实例,然后再销毁 Spring 容器。


总结

1,Bean作用域介绍?

Bean作用域指的是在Spring框架中,定义了Bean实例的创建和销毁方式,以及可以访问该实例的范围,并决定了每次通过容器获取Bean时返回的是同一个实例还是不同的实例。Bean作用域有以下6种,分别为:

  1. Singleton:单例作用域【Spring 默认作用域】
  2. Prototype:原型作用域【也称多例作用域】
  3. Request:请求作用域【限定于Spring MVC 使用】
  4. Session:会话作用域【限定于Spring MVC 使用】
  5. Application:全局作用域【限定于Spring MVC 使用】
  6. Websocket:HTTP WebSocket 作用域【限定于Spring WebSocket 使用】

2,Bean作用域的设置?

使用@Scope标签就可以用来声明Bean的作用域,@Scope 标签既可以修饰方法也可以修饰类。

@Scope 有两种设置方式,分别为直接设置值和使用枚举设置。

1,直接设置值:

@Scope("prototype")

2,使用枚举设置:

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

3,Bean生命周期流程?

Bean的生命周期指的是Bean对象由诞生到销毁的过程,可大致分为以下5步:

1,Bean实例化:Spring 容器根据配置或注解创建Bean的实例,为其分配内存空间。

2,属性设置:Spring容器会通过依赖注入【DI】或自动装配【Autowiring】的方式将配置的属性值设置给Bean的对应属性

3,初始化:

  • 各种通知:Spring容器会检测Bean是否实现了特定的Aware接口,然后通过这些接口回调方法通知Bean获取相关的信息。
  • 初始化前置方法:检测所有注册的BeanPostProcessor接口的实现类,并依次调用它们的前置处理方法。
  • 初始化方法:调用Bean的实际初始化方法,可简单地看作是Bean的构造完成后,进行一些额外的初始化工作的方法。
  • 初始化后置方法:会继续调用所有注册的BeanPostProcessor接口的实现类,并依次调用它们的后置处理方法。

4,使用Bean:Bean就可以在应用程序中根据业务逻辑调用和操作Bean。

5,销毁Bean:Spring容器将调用Bean的销毁方法,这可以将其简单地看作清理资源、释放连接等操作的方法。

Bean生命周期基本流程图:

【框架篇】Bean作用域和生命周期_第7张图片


结语

这就是本期博客的全部内容啦!如果有什么其他的问题无法自己解决,可以在评论区留言哦!

最后,如果你觉得这篇文章写的还不错的话或者有所收获的话,麻烦小伙伴们动动你们的小手,给个三连呗(点赞,评论✍,收藏),多多支持一下!各位的支持是我最大的动力,后期不断更新优质的内容来帮助大家,一起进步。那我们下期见!


你可能感兴趣的:(Java,EE【进阶】,spring,java-ee,java)