目录
- [1. 什么是 Bean 的生命周期?](#1. 什么是 Bean 的生命周期?)
- [2. 生命周期全景图](#2. 生命周期全景图)
- [3. 第一阶段:实例化(Instantiation)](#3. 第一阶段:实例化(Instantiation))
- [4. 第二阶段:属性填充(Population)](#4. 第二阶段:属性填充(Population))
- [5. 第三阶段:初始化(Initialization)](#5. 第三阶段:初始化(Initialization))
- [6. 第四阶段:使用(In Use)](#6. 第四阶段:使用(In Use))
- [7. 第五阶段:销毁(Destruction)](#7. 第五阶段:销毁(Destruction))
- [8. 源码追踪:从 refresh() 到 Bean 诞生](#8. 源码追踪:从 refresh() 到 Bean 诞生)
- [9. 实战演示:亲眼看到每个回调的执行顺序](#9. 实战演示:亲眼看到每个回调的执行顺序)
- [10. BeanPostProcessor------Spring 最强大的扩展点](#10. BeanPostProcessor——Spring 最强大的扩展点)
- [11. 面试题精选与回答思路](#11. 面试题精选与回答思路)
- [12. 总结](#12. 总结)
1. 什么是 Bean 的生命周期?
先从生活说起
每个人都有生命周期:出生 → 成长 → 工作 → 退休。
Spring 中的 Bean 也一样,它不是凭空出现在容器中的,而是经历了一系列明确的阶段:
Bean 的一生:
出生(实例化)→ 打疫苗/上学(属性填充 + 初始化)→ 上班干活(使用)→ 退休(销毁)
官方定义
Spring 官方文档对 Bean 生命周期的描述:
The Spring IoC container manages the lifecycle of beans. The container creates and manages beans according to the configuration metadata. Spring provides several mechanisms for you to interact with the bean lifecycle management.
翻译:Spring IoC 容器管理 Bean 的生命周期。容器根据配置元数据来创建和管理 Bean。Spring 提供了多种机制让你介入 Bean 的生命周期管理。
通俗理解 :Bean 的生命周期就是 Spring 容器创建 Bean、配置 Bean、使用 Bean、销毁 Bean 的完整过程。在这个过程的各个节点上,Spring 提供了"钩子"(回调方法),让你可以在特定时机执行自定义逻辑。
2. 生命周期全景图
先看全貌,再逐一深入:
┌──────────────────────────────────────────────────────────────┐
│ Spring Bean 生命周期 │
│ │
│ ┌─────────────┐ │
│ │ 第一阶段 │ 实例化(Instantiation) │
│ │ "出生" │ → 调用构造方法,创建对象 │
│ └──────┬──────┘ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 第二阶段 │ 属性填充(Population) │
│ │ "打疫苗" │ → @Autowired 注入依赖 │
│ └──────┬──────┘ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 第三阶段 │ 初始化(Initialization) │
│ │ "岗前培训" │ → Aware 回调 → @PostConstruct → afterPropertiesSet → init-method │
│ └──────┬──────┘ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 第四阶段 │ 使用(In Use) │
│ │ "上班干活" │ → Bean 在容器中被正常使用 │
│ └──────┬──────┘ │
│ ▼ │
│ ┌─────────────┐ │
│ │ 第五阶段 │ 销毁(Destruction) │
│ │ "退休" │ → @PreDestroy → destroy() → destroy-method │
│ └─────────────┘ │
└──────────────────────────────────────────────────────────────┘
每个阶段内部还有更细的步骤,接下来逐一讲解。
3. 第一阶段:实例化(Instantiation)
做了什么?
Spring 通过调用构造方法 来创建 Bean 的实例。此时对象已经"出生"了,但它的字段还没有被赋值(还是 null)。
生活比喻
婴儿刚出生------人是出来了,但什么都不会,什么都没有。
对应的源码
Spring 中负责实例化 Bean 的核心方法在 AbstractAutowireCapableBeanFactory 类中:
java
// AbstractAutowireCapableBeanFactory.java(简化版)
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) {
// ▶ 第一步:实例化 --- 调用构造方法创建对象
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
Object bean = instanceWrapper.getWrappedInstance();
// ▶ 第二步:属性填充(下一节讲)
populateBean(beanName, mbd, instanceWrapper);
// ▶ 第三步:初始化(再下一节讲)
exposedObject = initializeBean(beanName, exposedObject, mbd);
return exposedObject;
}
createBeanInstance() 方法内部会决定用哪个构造方法来创建对象:
java
// AbstractAutowireCapableBeanFactory.java(简化版)
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// 1. 如果有工厂方法(@Bean 方法),用工厂方法创建
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 2. 如果有带参构造方法,用带参构造方法创建(构造器注入)
// 3. 否则用无参构造方法创建
return instantiateBean(beanName, mbd);
}
关键点
- 实例化之后,对象已经在内存中了
- 但
@Autowired的字段此时还是null(还没注入) - 如果构造方法有参数(构造器注入),Spring 会在这一步就把依赖找到并传入
4. 第二阶段:属性填充(Population)
做了什么?
Spring 把 Bean 依赖的其他对象(通过 @Autowired、@Value、@Resource 等标注的字段)注入进来。
生活比喻
婴儿出生后,护士给他打疫苗、穿衣服、戴手环------把需要的东西一样一样地"装"上去。
对应的源码
java
// AbstractAutowireCapableBeanFactory.java(简化版)
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
// 1. 获取所有 BeanPostProcessor,找到处理注入的那些
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorsCache().instantiationAware) {
// 2. AutowiredAnnotationBeanPostProcessor 在这里处理 @Autowired 和 @Value
// 3. CommonAnnotationBeanPostProcessor 在这里处理 @Resource
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
}
// 4. 将属性值真正设置到 Bean 的字段上
applyPropertyValues(beanName, mbd, bw, pvs);
}
实际处理 @Autowired 注入的是 AutowiredAnnotationBeanPostProcessor:
java
// AutowiredAnnotationBeanPostProcessor.java(简化版)
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 1. 找到 bean 中所有标了 @Autowired 的字段和方法
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
// 2. 逐个注入
metadata.inject(bean, beanName, pvs);
return pvs;
}
关键点
- 属性填充完成后,Bean 的所有依赖都已经就位
@Autowired的底层就是通过AutowiredAnnotationBeanPostProcessor在这个阶段完成的@Resource则是通过CommonAnnotationBeanPostProcessor处理的
5. 第三阶段:初始化(Initialization)
这是生命周期中步骤最多、最复杂的阶段,也是面试中问得最细的部分。
做了什么?
依赖注入完成后,Spring 会依次调用一系列"回调方法",让 Bean 有机会做一些自定义的初始化操作。
生活比喻
小孩长大了,开始上学:先告诉他"你叫什么名字"(Aware 回调),然后参加岗前培训(初始化方法),最后正式上岗。
初始化阶段的完整执行顺序
属性填充完成
↓
① Aware 接口回调
→ BeanNameAware.setBeanName() "告诉你,你在容器中叫什么名字"
→ BeanFactoryAware.setBeanFactory() "告诉你,你在哪个工厂里"
→ ApplicationContextAware.setApplicationContext() "告诉你,你在哪个容器里"
↓
② BeanPostProcessor.postProcessBeforeInitialization()
→ 所有 BeanPostProcessor 的"前置处理"
→ @PostConstruct 就是在这一步被调用的!
↓
③ InitializingBean.afterPropertiesSet()
→ 如果 Bean 实现了 InitializingBean 接口
↓
④ 自定义 init-method
→ @Bean(initMethod = "init") 指定的方法
↓
⑤ BeanPostProcessor.postProcessAfterInitialization()
→ 所有 BeanPostProcessor 的"后置处理"
→ AOP 代理就是在这一步创建的!
↓
Bean 初始化完成,可以使用了
对应的源码
java
// AbstractAutowireCapableBeanFactory.java(简化版)
protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
// ① Aware 回调
invokeAwareMethods(beanName, bean);
// ② BeanPostProcessor 前置处理(@PostConstruct 在这里执行)
Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
// ③ + ④ InitializingBean.afterPropertiesSet() + 自定义 init-method
invokeInitMethods(beanName, wrappedBean, mbd);
// ⑤ BeanPostProcessor 后置处理(AOP 代理在这里创建)
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
}
我们来逐一看每个步骤的源码。
① Aware 回调
java
// AbstractAutowireCapableBeanFactory.java
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware beanNameAware) {
beanNameAware.setBeanName(beanName); // 告诉 Bean "你叫什么名字"
}
if (bean instanceof BeanClassLoaderAware classLoaderAware) {
classLoaderAware.setBeanClassLoader(classLoader); // 告诉 Bean "类加载器是哪个"
}
if (bean instanceof BeanFactoryAware beanFactoryAware) {
beanFactoryAware.setBeanFactory(beanFactory); // 告诉 Bean "你在哪个工厂里"
}
}
}
什么时候需要实现 Aware 接口? 当你的 Bean 需要获取 Spring 容器本身的一些信息时。比如你想在 Bean 内部获取 ApplicationContext:
java
@Component
public class MyBean implements ApplicationContextAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext context) {
this.context = context; // Spring 自动调用这个方法,把容器引用传给你
}
}
② BeanPostProcessor 前置处理
java
// AbstractAutowireCapableBeanFactory.java
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) return result;
result = current;
}
return result;
}
这一步会遍历容器中所有的 BeanPostProcessor,依次调用它们的 postProcessBeforeInitialization() 方法。
@PostConstruct 就是在这一步被处理的。 负责处理它的是 CommonAnnotationBeanPostProcessor(实现了 BeanPostProcessor 接口),它在 postProcessBeforeInitialization() 中扫描 Bean 的方法,找到标了 @PostConstruct 的方法并调用。
③ InitializingBean.afterPropertiesSet()
java
// AbstractAutowireCapableBeanFactory.java
protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd) {
// ③ 如果 Bean 实现了 InitializingBean 接口,调用 afterPropertiesSet()
if (bean instanceof InitializingBean initializingBean) {
initializingBean.afterPropertiesSet();
}
// ④ 如果配置了自定义 init-method,通过反射调用它
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
⑤ BeanPostProcessor 后置处理
java
// AbstractAutowireCapableBeanFactory.java
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) return result;
result = current;
}
return result;
}
AOP 代理就是在这一步创建的。 AnnotationAwareAspectJAutoProxyCreator(也是一个 BeanPostProcessor)在 postProcessAfterInitialization() 中检查 Bean 是否需要被代理,如果需要,就创建代理对象并返回。这就是为什么你 @Autowired 注入的 Bean 实际上可能是代理对象而不是原始对象。
三种初始化方式的执行顺序
如果你同时使用了三种初始化方式,它们的执行顺序是固定的:
@PostConstruct 方法 ← 最先执行(在 BeanPostProcessor 前置处理阶段)
↓
InitializingBean.afterPropertiesSet() ← 第二个执行
↓
自定义 init-method ← 最后执行
6. 第四阶段:使用(In Use)
做了什么?
初始化完成后,Bean 就"上岗"了------它待在 Spring 容器中,等着被其他 Bean 使用。
java
@RestController
public class UserController {
@Autowired
private UserService userService; // ← 这里拿到的就是已经完成所有生命周期的 Bean
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id); // 正常使用
}
}
关键点
- 对于 singleton 作用域的 Bean(默认),它会一直待在容器中,直到容器关闭
- 对于 prototype 作用域的 Bean,Spring 创建完就"不管了"------不会调用销毁方法
7. 第五阶段:销毁(Destruction)
做了什么?
当 Spring 容器关闭时(比如应用停止),Spring 会依次调用 Bean 的销毁方法,让 Bean 有机会释放资源(关闭数据库连接、停止线程池等)。
生活比喻
员工退休前,要做交接工作------归还公司电脑、交接客户资料、清理工位。
销毁阶段的执行顺序
容器开始关闭
↓
① @PreDestroy 标注的方法 ← 最先执行
↓
② DisposableBean.destroy() ← 第二个执行
↓
③ 自定义 destroy-method ← 最后执行
↓
Bean 被销毁
对应的源码
java
// DisposableBeanAdapter.java(简化版)
public void destroy() {
// ① @PreDestroy(通过 CommonAnnotationBeanPostProcessor 的 DestructionAwareBeanPostProcessor)
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
// ② DisposableBean.destroy()
if (this.invokeDisposableBean) {
((DisposableBean) this.bean).destroy();
}
// ③ 自定义 destroy-method
if (this.destroyMethodName != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
}
常见用途
java
@Component
public class ConnectionPool implements DisposableBean {
@PreDestroy
public void cleanup() {
System.out.println("@PreDestroy: 开始清理连接池...");
}
@Override
public void destroy() {
System.out.println("DisposableBean: 关闭所有数据库连接");
}
}
关键点
- 只有 singleton 的 Bean 才会被 Spring 调用销毁方法
- prototype 的 Bean,Spring 创建后就不管了,不会调用销毁方法
- 销毁方法的典型用途:关闭连接池、释放文件句柄、停止后台线程
8. 源码追踪:从 refresh() 到 Bean 诞生
现在我们来从更高的层面看------Spring 容器启动时,Bean 是在哪一步被创建的?
起点:AbstractApplicationContext.refresh()
这是 Spring 容器启动的总入口,也是一个经典的模板方法(参见我们的设计模式博客):
java
// AbstractApplicationContext.java(简化版)
public void refresh() {
// 1. 准备刷新
prepareRefresh();
// 2. 获取 BeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 准备 BeanFactory
prepareBeanFactory(beanFactory);
// 4. 后处理 BeanFactory(子类扩展点)
postProcessBeanFactory(beanFactory);
// 5. 执行 BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册 BeanPostProcessor(重要!为后面的生命周期回调做准备)
registerBeanPostProcessors(beanFactory);
// 7-10. 初始化消息源、事件广播器、注册监听器等...
// 11. ★ 实例化所有非懒加载的 singleton Bean ★
finishBeanFactoryInitialization(beanFactory);
// 12. 完成刷新
finishRefresh();
}
Bean 的创建发生在第 11 步 finishBeanFactoryInitialization()。
追踪调用链
refresh()
→ finishBeanFactoryInitialization(beanFactory)
→ beanFactory.preInstantiateSingletons()
→ getBean(beanName)
→ doGetBean(beanName)
→ createBean(beanName, mbd, args)
→ doCreateBean(beanName, mbd, args) ← 这就是我们在第3节看到的方法!
→ createBeanInstance() ← 第一阶段:实例化
→ populateBean() ← 第二阶段:属性填充
→ initializeBean() ← 第三阶段:初始化
在 IDEA 中调试验证
你可以在以下方法上设置断点,启动 Spring Boot 应用后观察调用栈:
| 断点位置 | 对应阶段 |
|---|---|
AbstractAutowireCapableBeanFactory.createBeanInstance() |
实例化 |
AbstractAutowireCapableBeanFactory.populateBean() |
属性填充 |
AbstractAutowireCapableBeanFactory.initializeBean() |
初始化 |
AbstractAutowireCapableBeanFactory.invokeAwareMethods() |
Aware 回调 |
CommonAnnotationBeanPostProcessor.postProcessBeforeInitialization() |
@PostConstruct |
InitializingBean.afterPropertiesSet() |
afterPropertiesSet |
在调试器的 Frames(栈帧) 窗口中,你能看到从 refresh() 一路调用到当前方法的完整链路。这就是源码阅读博客中提到的"调用栈就是自动生成的执行流程图"。
9. 实战演示:亲眼看到每个回调的执行顺序
写一个 Demo 类,同时实现所有生命周期回调接口,看看它们的执行顺序:
java
@Component
public class LifecycleDemo implements BeanNameAware, BeanFactoryAware,
ApplicationContextAware, InitializingBean, DisposableBean {
private String beanName;
public LifecycleDemo() {
System.out.println("1. 【构造方法】调用构造方法,实例化 Bean");
}
// ========== 属性填充 ==========
@Autowired
public void setDependency(SomeService someService) {
System.out.println("2. 【属性填充】@Autowired 注入依赖");
}
// ========== Aware 回调 ==========
@Override
public void setBeanName(String name) {
this.beanName = name;
System.out.println("3. 【BeanNameAware】setBeanName() → 我的名字是: " + name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
System.out.println("4. 【BeanFactoryAware】setBeanFactory()");
}
@Override
public void setApplicationContext(ApplicationContext ctx) {
System.out.println("5. 【ApplicationContextAware】setApplicationContext()");
}
// ========== 初始化 ==========
@PostConstruct
public void postConstruct() {
System.out.println("6. 【@PostConstruct】执行初始化方法");
}
@Override
public void afterPropertiesSet() {
System.out.println("7. 【InitializingBean】afterPropertiesSet()");
}
// 如果配了 @Bean(initMethod = "customInit"),这个方法会在 afterPropertiesSet 之后调用
public void customInit() {
System.out.println("8. 【自定义 init-method】customInit()");
}
// ========== 销毁 ==========
@PreDestroy
public void preDestroy() {
System.out.println("9. 【@PreDestroy】执行销毁前方法");
}
@Override
public void destroy() {
System.out.println("10.【DisposableBean】destroy()");
}
// 如果配了 @Bean(destroyMethod = "customDestroy"),这个方法会在 destroy 之后调用
public void customDestroy() {
System.out.println("11.【自定义 destroy-method】customDestroy()");
}
}
控制台输出
启动应用后,你会在控制台看到以下输出(按顺序):
1. 【构造方法】调用构造方法,实例化 Bean
2. 【属性填充】@Autowired 注入依赖
3. 【BeanNameAware】setBeanName() → 我的名字是: lifecycleDemo
4. 【BeanFactoryAware】setBeanFactory()
5. 【ApplicationContextAware】setApplicationContext()
6. 【@PostConstruct】执行初始化方法
7. 【InitializingBean】afterPropertiesSet()
关闭应用时:
9. 【@PreDestroy】执行销毁前方法
10.【DisposableBean】destroy()
记忆口诀
构造 → 注入 → Aware → @PostConstruct → afterPropertiesSet → init-method
(使用阶段)
@PreDestroy → destroy() → destroy-method
简化记忆:"生(构造)→ 注(注入)→ 知(Aware)→ 前(PostConstruct)→ 后(afterPropertiesSet)→ 用 → 预(PreDestroy)→ 销(destroy)"
10. BeanPostProcessor------Spring 最强大的扩展点
为什么单独讲它?
在 Bean 生命周期中,BeanPostProcessor 是一个非常特殊的存在 ------它不是作用于单个 Bean 的,而是作用于容器中所有 Bean 的。Spring 自身的很多核心功能(@Autowired 注入、@PostConstruct 调用、AOP 代理创建)都是通过 BeanPostProcessor 实现的。
接口定义
java
public interface BeanPostProcessor {
// 在初始化之前调用(在 @PostConstruct 之前的一个时机点)
default Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
// 在初始化之后调用(AOP 代理在这里创建)
default Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
它的执行时机
属性填充完成
↓
Aware 回调
↓
★ BeanPostProcessor.postProcessBeforeInitialization() ★ ← 所有 BPP 的前置方法
↓
InitializingBean.afterPropertiesSet()
↓
自定义 init-method
↓
★ BeanPostProcessor.postProcessAfterInitialization() ★ ← 所有 BPP 的后置方法
每个 Bean 在初始化阶段,都会经过所有 BeanPostProcessor 的"过手"。
Spring 内置的重要 BeanPostProcessor
| BeanPostProcessor | 职责 |
|---|---|
AutowiredAnnotationBeanPostProcessor |
处理 @Autowired 和 @Value 注入 |
CommonAnnotationBeanPostProcessor |
处理 @Resource、@PostConstruct、@PreDestroy |
AnnotationAwareAspectJAutoProxyCreator |
创建 AOP 代理对象 |
ApplicationContextAwareProcessor |
处理 ApplicationContextAware 等回调 |
自定义 BeanPostProcessor 示例
java
@Component
public class TimingBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("【BPP 前置】正在初始化: " + beanName);
return bean; // 必须返回 bean,否则后续流程拿不到对象
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("【BPP 后置】初始化完成: " + beanName);
return bean; // 你也可以返回一个代理对象来替换原始 Bean
}
}
关键理解
BeanPostProcessor 是 Spring 实现各种"魔法"的核心机制。 理解了它,你就理解了:
- 为什么
@Autowired能自动注入(因为有AutowiredAnnotationBeanPostProcessor) - 为什么
@PostConstruct能被调用(因为有CommonAnnotationBeanPostProcessor) - 为什么加了
@Transactional的类会变成代理(因为有AnnotationAwareAspectJAutoProxyCreator)
11. 面试题精选与回答思路
题目一:请描述 Spring Bean 的生命周期
回答思路(分阶段回答,条理清晰):
Spring Bean 的生命周期可以分为五个大阶段:
- 实例化:Spring 通过构造方法(或工厂方法)创建 Bean 实例
- 属性填充 :通过
@Autowired、@Resource等注解注入依赖- 初始化 :依次执行 Aware 回调 →
@PostConstruct→afterPropertiesSet()→ 自定义 init-method。在初始化前后,BeanPostProcessor会介入处理- 使用:Bean 在容器中被正常使用
- 销毁 :容器关闭时,依次执行
@PreDestroy→destroy()→ 自定义 destroy-method
题目二:@PostConstruct、afterPropertiesSet、init-method 的区别和执行顺序?
执行顺序 :
@PostConstruct→afterPropertiesSet()→init-method区别:
@PostConstruct:Jakarta 标准注解,通过BeanPostProcessor机制实现,最通用afterPropertiesSet():需要实现InitializingBean接口,和 Spring 框架耦合init-method:通过@Bean(initMethod = "xxx")指定,适合第三方库(不能改源码加注解时)
题目三:BeanPostProcessor 和 BeanFactoryPostProcessor 的区别?
BeanPostProcessor:作用于 Bean 实例------在每个 Bean 初始化前后做处理BeanFactoryPostProcessor:作用于 Bean 定义------在所有 Bean 实例化之前,修改 Bean 的配置元数据比喻:
BeanFactoryPostProcessor修改的是"配方"(还没做菜之前改食谱),BeanPostProcessor处理的是"成品"(菜做出来之后加调料)。
题目四:Spring 是如何解决循环依赖的?
Spring 使用三级缓存 来解决 singleton Bean 之间通过属性注入(
@Autowired)产生的循环依赖:
缓存 名称 存的内容 一级缓存 singletonObjects完全初始化好的 Bean 二级缓存 earlySingletonObjects提前曝光的半成品 Bean(已实例化,未初始化) 三级缓存 singletonFactoriesBean 的工厂对象(用于创建代理) 核心流程:A 依赖 B,B 依赖 A
- 创建 A → 实例化 A → 把 A 的工厂放入三级缓存 → 填充 A 的属性 → 发现需要 B
- 创建 B → 实例化 B → 填充 B 的属性 → 发现需要 A → 从三级缓存拿到 A 的早期引用
- B 初始化完成 → 回到 A 的属性填充 → A 拿到 B → A 初始化完成
注意 :构造器注入的循环依赖 Spring 无法解决(因为实例化都完不成,没法放入缓存)。
12. 总结
生命周期完整流程(精简版)
构造方法(实例化)
↓
@Autowired / @Resource(属性填充)
↓
BeanNameAware / BeanFactoryAware / ApplicationContextAware(Aware 回调)
↓
BeanPostProcessor.postProcessBeforeInitialization()(前置处理)
↓
@PostConstruct(注解初始化)
↓
InitializingBean.afterPropertiesSet()(接口初始化)
↓
init-method(自定义初始化)
↓
BeanPostProcessor.postProcessAfterInitialization()(后置处理,AOP 在此创建代理)
↓
===== Bean 可以使用了 =====
↓
@PreDestroy(注解销毁)
↓
DisposableBean.destroy()(接口销毁)
↓
destroy-method(自定义销毁)
核心源码对照表
| 生命周期阶段 | 对应源码方法 | 所在类 |
|---|---|---|
| 实例化 | createBeanInstance() |
AbstractAutowireCapableBeanFactory |
| 属性填充 | populateBean() |
AbstractAutowireCapableBeanFactory |
| Aware 回调 | invokeAwareMethods() |
AbstractAutowireCapableBeanFactory |
| BPP 前置 | applyBeanPostProcessorsBeforeInitialization() |
AbstractAutowireCapableBeanFactory |
| 初始化方法 | invokeInitMethods() |
AbstractAutowireCapableBeanFactory |
| BPP 后置 | applyBeanPostProcessorsAfterInitialization() |
AbstractAutowireCapableBeanFactory |
| 销毁 | destroy() |
DisposableBeanAdapter |
一句话总结
Bean 的生命周期 = Spring 容器创建、配置、使用、销毁 Bean 的完整过程。核心代码都在
AbstractAutowireCapableBeanFactory.doCreateBean()方法中------实例化、属性填充、初始化三步走。理解了这个方法,就理解了 Bean 生命周期的 80%。