深度解析 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生命周期的定制化管理。
- Bean的定义阶段: 在这个阶段,Spring会解析Bean的定义,包括从配置文件中读取Bean的元数据,例如类名、属性值、依赖关系等。这个阶段的主要目标是将Bean的定义加载到Spring的应用上下文中。
- Bean的实例化阶段: 一旦Bean的定义加载到容器中,Spring会根据这些定义创建Bean的实例。这可能涉及到通过构造函数或工厂方法创建实例,并将依赖项注入到Bean中。在这个阶段,Spring会创建Bean的原始对象,并将其放入容器中。
- Bean的初始化阶段: 在这个阶段,Spring会对Bean进行初始化。这包括执行任何在Bean实例化之后需要执行的定制逻辑,例如调用初始化方法、应用BeanPostProcessors等。这个阶段是在Bean实例创建完成后、在将Bean实例提供给应用程序之前执行的。
- Bean的销毁阶段: 最后一个阶段是Bean的销毁。在容器关闭或者特定的销毁时机触发时,Spring会调用Bean的销毁方法,执行清理工作,例如释放资源、关闭连接等。这个阶段是确保Bean在不再需要时能够正确地释放资源。
二、Bean生命周期流程图
Bean的生命周期执行步骤:
- Bean实例化:当Spring容器启动时,它会创建Bean的实例。这通常是通过调用Bean的构造函数来完成的。
- Bean属性注入:在Bean实例化之后,Spring会进行属性注入。这是将外部数据或配置信息设置到Bean的属性中的过程。
- BeanNameAware接口的setBeanName方法调用:如果Bean实现了BeanNameAware接口,那么在Bean被初始化之前,Spring会调用其setBeanName方法,并传递给它一个字符串,表示Bean的名称。
- BeanFactoryAware接口的setBeanFactory方法调用:如果Bean实现了BeanFactoryAware接口,那么在Bean被初始化之前,Spring会调用其setBeanFactory方法,并传递给它一个BeanFactory对象,以便Bean可以访问工厂的其他Bean。(同理~调用ApplicationContextAware接口的setApplicationContext()方法)
- BeanPostProcessor接口的初始化之前方法调用:在Bean的属性注入之后,但在初始化之前,Spring将调用BeanPostProcessor接口的postProcessBeforeInitialization方法来对bean执行一些额外的操作。
- InitializingBean接口的afterPropertiesSet方法调用:如果Bean实现了InitializingBean接口,并且在它的afterPropertiesSet方法中被调用之前,Spring会尝试对其进行属性注入。
- BeanPostProcessor接口的初始化之前方法调用:在Bean的属性注入之后,但在初始化之后,Spring将调用BeanPostProcessor接口的postProcessAfterInitialization方法来对bean执行一些额外的操作。
- Bean正常使用:在Bean完成所有必要的初始化之后,它就可以被使用了。这时,应用程序可以通过依赖注入或其他方式获取Bean的引用,并进行相应的操作。
- DisposableBean接口的destroy方法调用:当Spring容器关闭时,它会销毁Bean。如果Bean实现了DisposableBean接口,那么在Bean被销毁之前,Spring会调用其destroy方法。
- 自定义销毁方法调用:除了上面的标准方法外,还可以为Bean定义自定义的销毁方法,并在容器关闭时自动调用。
三、Bean生命周期验证
本文使用 Spring Framework 的注解来描述一个完整的 Bean 生命周期。Bean 的完整生命周期,包括创建、初始化、使用和销毁。
3.1 代码案例
演示 Bean 的完整生命周期Demo:
- 配置类: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(); } }
- 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引用..."); } }
- 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 执行结果
四、Bean生命周期源码
需要调试运行看Bean生命周期的读者可自行尝试哈,本文主要解读部分相对重要的源码,亲测一直nextStep,根本点不完-_-,头昏眼花,哈哈哈哈我是菜鸡
4.1 setBeanName()
Bean 实现了 BeanNameAware 接口时,容器在初始化 Bean 时会调用其 setBeanName() 方法,从而允许 Bean 在初始化阶段获取自己在容器中的名字。
4.2 setBeanFactory()
BeanFactoryAware 接口允许一个 Bean 在初始化阶段获得对自己所在的 BeanFactory 的引用,从而可以与容器进行交互,例如动态地获取其他 Bean 实例或执行特定的逻辑。
4.3 setApplicationContext()
ApplicationContextAware 接口允许一个 Bean 在初始化阶段获得对自己所在的 ApplicationContext 的引用,从而可以与容器进行交互,例如动态地获取其他 Bean 实例或执行特定的逻辑。 (细心的读者发现这个视乎和前面类似,读者可看我前面的文章,有细说BeanFactory 和ApplicationContext 的区别)
4.4 postProcessBeforeInitialization()
BeanPostProcessor 接口定义了两个默认方法,分别用于在初始化 Bean 之前和之后对其进行一些自定义处理,但默认情况下不对 Bean 进行修改。
4.5 afterPropertiesSet()
InitializingBean 接口定义了一个方法 afterPropertiesSet(),用于在 Bean 的属性设置之后执行自定义的初始化逻辑。
4.6 postProcessAfterInitialization()
BeanPostProcessor 接口定义了两个默认方法,分别用于在初始化 Bean 之前和之后对其进行一些自定义处理,但默认情况下不对 Bean 进行修改。 (与4.4相同,只是调用的顺序不同,结合一起看哈)
4.7 destroy()
Bean准备就绪,可被应用程序使用,且一直驻留在应用上下文中,直到应用上下文被销毁。 DisposableBean 接口定义了一个方法 destroy(),用于在 Bean 销毁之前执行自定义的清理逻辑。
ps:想要了解各个方法的实现类的读者可自行解读相应的源码。
知识象烛光,能照亮一个人,也能照亮无数人