• 2023.11.13 Spring Bean 的生命周期


    目录

    Spring 执行流程

    Bean 的生命周期 

    五个阶段

    深入理解 Bean 初始化

    实例理解 

    总结梳理

    经典面试题 


    Spring 执行流程

    Bean 的生命周期 

    • Spring 中 Bean 的生命周就是 Bean 在 Spring 中从创建到销毁的整个过程


    五个阶段

    1. 实例化 Bean

    • 为 Bean 对象分配内存空间

    2. 设置属性

    • Spring 通过反射机制给 Bean 的属性赋值

    3. Bean 初始化

    • 各种通知
    • 初始化前置方法
    • 初始化方法
    • 初始化后置方法

    4. 使用 Bean

    5. 销毁 Bean


    深入理解 Bean 初始化

    各种通知接口方法

    • BeanNameAware:允许 Bean 获取自己在容器中的名称
    • BeanFactoryAware:允许 Bean 获取对 Beanfactory的引用
    • ApplicationContextAware:允许 Bean 获取对 ApplicationContext 的引用

    初始化前置方法

    • 该方法可以用于执行一些预处理操作,例如 设置一些默认属性或检查依赖关系

    初始化方法

    • 如果使用注解方式,可以使用 @PostConstruct 注解来标记初始化方法
    • 如果使用 XML 配置方式,可以在 标签中使用 init-method 属性来指定初始化方法的名称

    初始化后置方法

    • 该方法可以用于执行一些后续操作,例如资源清理、启动定时任务等

    注意:

    • 实例化和初始化是两个完全不同的过程
    • 实例化只是给Bean对象分配内存空间
    • 初始化则是将程序执行权从系统级别转到用户级别,执行用户添加的业务代码

    实例理解 

    • 创建一个 BeanComponent 类

    • 在 Spring-config.xml 中使用 标签将 BeanComponent 类的 Bean 对象注入到Spring 容器中

    •  BeanComponent 类设置 BeanNameAware 通知、两种初始化方法、销毁时执行的方法
    • sayHi 方法的创建是为了 使用 Bean 对象
    1. import org.springframework.beans.factory.BeanNameAware;
    2. import javax.annotation.PostConstruct;
    3. import javax.annotation.PreDestroy;
    4. public class BeanComponent implements BeanNameAware {
    5. @Override
    6. public void setBeanName(String s) {
    7. System.out.println( "BeanName ——> " + s + " 执行了通知");
    8. }
    9. /*
    10. * xml 方式的初始化方法
    11. * */
    12. public void myInit() {
    13. System.out.println("XML 方式的初始化方法");
    14. }
    15. @PostConstruct
    16. public void doPostConstruct() {
    17. System.out.println("注解方式的初始化方法");
    18. }
    19. public void sayHi() {
    20. System.out.println("执行 sayHi 方法");
    21. }
    22. /*
    23. * 销毁时执行的方法
    24. * 此处使用注解的方式
    25. * */
    26. @PreDestroy
    27. public void doPreDestroy() {
    28. System.out.println("销毁时的方法 已执行");
    29. }
    30. }

    注意:

    • 在启动类中获取 BeanComponent 类的 Bean 对象,并调用其 sayHi 方法,最后销毁容器
    1. import com.java.demo.component.BeanComponent;
    2. import org.springframework.context.support.ClassPathXmlApplicationContext;
    3. public class App {
    4. public static void main(String[] args) {
    5. // 因为 ApplicationContext 中没有销毁方法,所以此处使用 ClassPathXmlApplicationContext
    6. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Spring-config.xml");
    7. BeanComponent beanComponent = context.getBean("beanComponent",BeanComponent.class);
    8. // 调用 sayHi 方法,即使用该 Bean 对象
    9. beanComponent.sayHi();
    10. // 将容器销毁
    11. context.destroy();
    12. }
    13. }

    运行结果:

    • 我们发现该执行结果,正好与我们的预期相符合

    总结梳理

    • Spring 执行流程和 Bean 的生命周期 结合理解

    • 加载配置文件:Spring 容器会先加载配置文件,例如 XML 文件或注解配置,以获取Bean 的定义和相关的配置信息
    • 创建容器:根据配置文件中的定义,Spring 容器会创建一个应用上下文,也就是容器对象,用于管理 Bean 的生命周期
    • 实例化 Bean:Spring 容器根据配置文件中的定义,实例化 Bean 对象,这是通过调用Bean 的构造函数来完成的
    • 设置 Bean 属性:一旦 Bean 实例化完成,Spring 容器会通过调用 Bean 的 setter 方法或直接访问其字段,将文件中定义的属性值注入到 Bean 中
    • 调用 Bean 的初始化方法:如果 Bean 实现了 InitializingBean 接口,Spring 容器会在属性注入完成后调用其定义的初始化方法。同时如果在配置文件中指定了自定义的初始化方法。Spring 容器也会调用该方法
    • 使用 Bean:在 Bean 的初始化完成后,Spring 容器会将其放入容器中,供其他 Bean 或应用程序使用
    • 调用 Bean 的销毁方法:当 Spring 容器关闭时,它会销毁之前先释放的 Bean 资源,如果 Bean 实现了 DisposableBean 接口,容器会在销毁前调用其定义的销毁方法。同时,如果在配置文件中指定了自定义的销毁方法,Spring 容器也会调用该方法

    经典面试题 

    是否可以先 执行初始化 再 执行设置属性 ?

    • 不可以
    • 因为初始化方法中可能会用到设置后的属性

    实例理解

    1. @Controller
    2. public class StudentController {
    3. //属性注入
    4. @Autowired
    5. private Student student;
    6. //初始化
    7. @PostConstruct
    8. public void init() {
    9. student.setName("xiaolin");
    10. }
    11. }
    • 如果此时先执行了初始化 init 方法
    • init 方法中需要使用属性注入后得到的 student 对象
    • 此时该 student 对象还未被 Spring 容器注入便被 init 方法进行修改
    • 上述过程,将直接引发空指针异常
  • 相关阅读:
    uniapp 小程序canvas插入网络图片
    【Java基础面试十五】、 说一说你对多态的理解
    利用go多态实现一个简单工厂模式
    qt自定义可删除标签控件、自适应布局
    每日一题(LeetCode)----数组--移除元素(三)
    回溯算法的应用
    商业建筑利用物联网设备实现能源效率的3种方式
    Navicat 安装及初步配置指南
    Unity Samples和帧动画的问题
    《Vue入门到精通系列之四》--- vue cli详解
  • 原文地址:https://blog.csdn.net/weixin_63888301/article/details/134387566