深度解析 Spring 源码:探寻Bean的生命周期

05-13 1547阅读

深度解析 Spring 源码:探寻Bean的生命周期

文章目录

    • 一、 Bean生命周期概述
    • 二、Bean生命周期流程图
    • 三、Bean生命周期验证
      • 3.1 代码案例
      • 3.2 执行结果
      • 四、Bean生命周期源码
        • 4.1 setBeanName()
        • 4.2 setBeanFactory()
        • 4.3 setApplicationContext()
        • 4.4 postProcessBeforeInitialization()
        • 4.5 afterPropertiesSet()
        • 4.6 postProcessAfterInitialization()
        • 4.7 destroy()

          一、 Bean生命周期概述

          Bean的生命周期包括了定义、实例化、初始化和销毁四个关键阶段,Spring框架在每个阶段都提供了钩子方法,允许开发者在特定的时机执行自定义的逻辑,从而实现对Bean生命周期的定制化管理。

          1. Bean的定义阶段: 在这个阶段,Spring会解析Bean的定义,包括从配置文件中读取Bean的元数据,例如类名、属性值、依赖关系等。这个阶段的主要目标是将Bean的定义加载到Spring的应用上下文中。
          2. Bean的实例化阶段: 一旦Bean的定义加载到容器中,Spring会根据这些定义创建Bean的实例。这可能涉及到通过构造函数或工厂方法创建实例,并将依赖项注入到Bean中。在这个阶段,Spring会创建Bean的原始对象,并将其放入容器中。
          3. Bean的初始化阶段: 在这个阶段,Spring会对Bean进行初始化。这包括执行任何在Bean实例化之后需要执行的定制逻辑,例如调用初始化方法、应用BeanPostProcessors等。这个阶段是在Bean实例创建完成后、在将Bean实例提供给应用程序之前执行的。
          4. Bean的销毁阶段: 最后一个阶段是Bean的销毁。在容器关闭或者特定的销毁时机触发时,Spring会调用Bean的销毁方法,执行清理工作,例如释放资源、关闭连接等。这个阶段是确保Bean在不再需要时能够正确地释放资源。

          二、Bean生命周期流程图

          深度解析 Spring 源码:探寻Bean的生命周期

          Bean的生命周期执行步骤:

          1. Bean实例化:当Spring容器启动时,它会创建Bean的实例。这通常是通过调用Bean的构造函数来完成的。
          2. Bean属性注入:在Bean实例化之后,Spring会进行属性注入。这是将外部数据或配置信息设置到Bean的属性中的过程。
          3. BeanNameAware接口的setBeanName方法调用:如果Bean实现了BeanNameAware接口,那么在Bean被初始化之前,Spring会调用其setBeanName方法,并传递给它一个字符串,表示Bean的名称。
          4. BeanFactoryAware接口的setBeanFactory方法调用:如果Bean实现了BeanFactoryAware接口,那么在Bean被初始化之前,Spring会调用其setBeanFactory方法,并传递给它一个BeanFactory对象,以便Bean可以访问工厂的其他Bean。(同理~调用ApplicationContextAware接口的setApplicationContext()方法)
          5. BeanPostProcessor接口的初始化之前方法调用:在Bean的属性注入之后,但在初始化之前,Spring将调用BeanPostProcessor接口的postProcessBeforeInitialization方法来对bean执行一些额外的操作。
          6. InitializingBean接口的afterPropertiesSet方法调用:如果Bean实现了InitializingBean接口,并且在它的afterPropertiesSet方法中被调用之前,Spring会尝试对其进行属性注入。
          7. BeanPostProcessor接口的初始化之前方法调用:在Bean的属性注入之后,但在初始化之后,Spring将调用BeanPostProcessor接口的postProcessAfterInitialization方法来对bean执行一些额外的操作。
          8. Bean正常使用:在Bean完成所有必要的初始化之后,它就可以被使用了。这时,应用程序可以通过依赖注入或其他方式获取Bean的引用,并进行相应的操作。
          9. DisposableBean接口的destroy方法调用:当Spring容器关闭时,它会销毁Bean。如果Bean实现了DisposableBean接口,那么在Bean被销毁之前,Spring会调用其destroy方法。
          10. 自定义销毁方法调用:除了上面的标准方法外,还可以为Bean定义自定义的销毁方法,并在容器关闭时自动调用。

          三、Bean生命周期验证

          本文使用 Spring Framework 的注解来描述一个完整的 Bean 生命周期。Bean 的完整生命周期,包括创建、初始化、使用和销毁。

          3.1 代码案例

          演示 Bean 的完整生命周期Demo:

          1. 配置类:AppConfig 类使用 @Configuration 注解定义 Spring 配置类,并声明了一个 Bean。
          package com.example.springdemo.bean;
          import org.springframework.context.annotation.Bean;
          import org.springframework.context.annotation.Configuration;
          @Configuration
          public class AppConfig {
              @Bean
              public MyBean myBeanDemo() {
                  return new MyBean();
              }
          }
          
          1. Bean 类:MyBean 类是我们要管理的 Bean。它包含一个 @PostConstruct 注解的 init() 方法,该方法将在 Bean 初始化后立即执行。此外,它还包含一个 @PreDestroy 注解的 destroy() 方法,该方法将在 Bean 销毁前执行。
          package com.example.springdemo.bean;
          import org.springframework.beans.BeansException;
          import org.springframework.beans.factory.*;
          import org.springframework.context.ApplicationContext;
          import org.springframework.context.ApplicationContextAware;
          import org.springframework.stereotype.Component;
          import javax.annotation.PostConstruct;
          import javax.annotation.PreDestroy;
          @Component
          public class MyBean implements BeanNameAware, BeanFactoryAware,
                  ApplicationContextAware, InitializingBean, DisposableBean {
              public MyBean() {
                  System.out.println("Bean 构造函数调用...");
              }
              @PostConstruct
              public void init() {
                  System.out.println("Bean 初始化...");
              }
              @PreDestroy
              public void destroy() {
                  System.out.println("Bean 销毁...");
              }
              public void performTask() {
                  System.out.println("Bean 正在执行任务...");
              }
              @Override
              public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
                  System.out.println("Bean 获得所在BeanFactory引用...");
              }
              @Override
              public void setBeanName(String s) {
                  System.out.println("Bean 名称...");
              }
              @Override
              public void afterPropertiesSet() throws Exception {
                  System.out.println("Bean 属性设置之后,自定义的初始化...");
              }
              @Override
              public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
                  System.out.println("Bean 获得所在ApplicationContext引用...");
              }
          }
          
          1. Main 类:Main 类是主程序入口,创建 Spring 应用程序上下文,获取 Bean 实例,并在使用完 Bean 后关闭上下文。
          package com.example.springdemo;
          import com.example.springdemo.bean.AppConfig;
          import com.example.springdemo.bean.MyBean;
          import org.springframework.boot.SpringApplication;
          import org.springframework.boot.autoconfigure.SpringBootApplication;
          import org.springframework.context.annotation.AnnotationConfigApplicationContext;
          @SpringBootApplication
          public class SpringDemoApplication {
          	public static void main(String[] args) {
          		SpringApplication.run(SpringDemoApplication.class, args);
          		// 创建 Spring 应用程序上下文
          		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
          		// 获取 MyBean 实例
          		MyBean bean = context.getBean(MyBean.class);
          		// 使用 Bean
          		bean.performTask();
          		// 关闭上下文
          		context.close();
          	}
          }
          

          3.2 执行结果

          深度解析 Spring 源码:探寻Bean的生命周期

          四、Bean生命周期源码

          需要调试运行看Bean生命周期的读者可自行尝试哈,本文主要解读部分相对重要的源码,亲测一直nextStep,根本点不完-_-,头昏眼花,哈哈哈哈我是菜鸡

          4.1 setBeanName()

          Bean 实现了 BeanNameAware 接口时,容器在初始化 Bean 时会调用其 setBeanName() 方法,从而允许 Bean 在初始化阶段获取自己在容器中的名字。

          深度解析 Spring 源码:探寻Bean的生命周期

          4.2 setBeanFactory()

          BeanFactoryAware 接口允许一个 Bean 在初始化阶段获得对自己所在的 BeanFactory 的引用,从而可以与容器进行交互,例如动态地获取其他 Bean 实例或执行特定的逻辑。

          深度解析 Spring 源码:探寻Bean的生命周期

          4.3 setApplicationContext()

          ApplicationContextAware 接口允许一个 Bean 在初始化阶段获得对自己所在的 ApplicationContext 的引用,从而可以与容器进行交互,例如动态地获取其他 Bean 实例或执行特定的逻辑。 (细心的读者发现这个视乎和前面类似,读者可看我前面的文章,有细说BeanFactory 和ApplicationContext 的区别)

          深度解析 Spring 源码:探寻Bean的生命周期

          4.4 postProcessBeforeInitialization()

          BeanPostProcessor 接口定义了两个默认方法,分别用于在初始化 Bean 之前和之后对其进行一些自定义处理,但默认情况下不对 Bean 进行修改。

          深度解析 Spring 源码:探寻Bean的生命周期

          4.5 afterPropertiesSet()

          InitializingBean 接口定义了一个方法 afterPropertiesSet(),用于在 Bean 的属性设置之后执行自定义的初始化逻辑。

          深度解析 Spring 源码:探寻Bean的生命周期

          4.6 postProcessAfterInitialization()

          BeanPostProcessor 接口定义了两个默认方法,分别用于在初始化 Bean 之前和之后对其进行一些自定义处理,但默认情况下不对 Bean 进行修改。 (与4.4相同,只是调用的顺序不同,结合一起看哈)

          深度解析 Spring 源码:探寻Bean的生命周期

          4.7 destroy()

          Bean准备就绪,可被应用程序使用,且一直驻留在应用上下文中,直到应用上下文被销毁。 DisposableBean 接口定义了一个方法 destroy(),用于在 Bean 销毁之前执行自定义的清理逻辑。

          深度解析 Spring 源码:探寻Bean的生命周期

          ps:想要了解各个方法的实现类的读者可自行解读相应的源码。

          知识象烛光,能照亮一个人,也能照亮无数人

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]