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

作者 : admin 本文共5300个字,预计阅读时间需要14分钟 发布时间: 2024-06-10 共2人阅读

深度解析 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的生命周期插图(1)

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的生命周期插图(2)

四、Bean生命周期源码

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

4.1 setBeanName()

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

深度解析 Spring 源码:探寻Bean的生命周期插图(3)

4.2 setBeanFactory()

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

深度解析 Spring 源码:探寻Bean的生命周期插图(4)

4.3 setApplicationContext()

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

深度解析 Spring 源码:探寻Bean的生命周期插图(5)

4.4 postProcessBeforeInitialization()

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

深度解析 Spring 源码:探寻Bean的生命周期插图(6)

4.5 afterPropertiesSet()

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

深度解析 Spring 源码:探寻Bean的生命周期插图(7)

4.6 postProcessAfterInitialization()

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

深度解析 Spring 源码:探寻Bean的生命周期插图(8)

4.7 destroy()

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

深度解析 Spring 源码:探寻Bean的生命周期插图(9)

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

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

本站无任何商业行为
个人在线分享 » 深度解析 Spring 源码:探寻Bean的生命周期
E-->