概述
在上一篇《IoC 设计哲学:容器、BeanDefinition 与配置元信息》中,我们深入剖析了 Spring IoC 容器如何将五花八门的配置元信息——XML、注解、Java Config——统一抽象为 BeanDefinition,并注册到容器内部的“图纸库”DefaultListableBeanFactory.beanDefinitionMap 中。当 XmlBeanDefinitionReader 或 ClassPathBeanDefinitionScanner 将配置元信息转化为一条条 BeanDefinition 之后,Bean 的生命周期便从图纸阶段正式启动。本文将从容器刷新过程中 finishBeanFactoryInitialization 的触发点开始,追踪一个 Bean 从图纸到成品、再到最终销毁的完整轨迹。
如果说 IoC 容器是 Spring 的心脏,那么 Bean 的生命周期就是血液流经全身的完整脉络。每一个由 Spring 管理的 Bean——无论是一个 @Service、一个 @Controller,还是一条数据源连接——都必须经历从定义、创建、装配、初始化到最终销毁的严格旅程。理解这条轨迹上每一个扩展点的执行时机与顺序,不仅是阅读 Spring 源码的基础,更是排查线上事故的利器。本文将以 AbstractAutowireCapableBeanFactory 为核心线索,全景呈现 Bean 生命的每一个细节,并结合源码与真实生产案例,让生命周期从枯燥的概念变为可诊断、可控制的工程能力。
- 全生命周期阶段:BeanDefinition 注册 → 实例化前拦截 → 实例化 →实例化后拦截 → 属性填充 → Aware 回调 → BeanPostProcessor 前置处理 → 初始化 → BeanPostProcessor 后置处理 → 就绪 → 容器关闭 → 销毁。每个阶段都有严格的顺序与依赖。
- 核心扩展点:
InstantiationAwareBeanPostProcessor可拦截实例化并提前返回代理;BeanPostProcessor提供初始化前后的通用扩展;InitializingBean与DisposableBean定义了初始化与销毁的契约。 - 回调顺序:
@PostConstruct先于InitializingBean.afterPropertiesSet执行,本质是因为CommonAnnotationBeanPostProcessor在postProcessBeforeInitialization中处理@PostConstruct,而afterPropertiesSet在invokeInitMethods中执行。 - 级联效应:例化前若返回非空代理,属性填充、Aware 回调、初始化全被跳过;属性填充若被
postProcessAfterInstantiation终止,依赖注入直接失效;@PostConstruct执行时 AOP 代理尚未创建,导致@Async、@Transactional静默失效。 - 生产事故根源:大量事故源于对后处理器顺序、代理提前暴露、初始化阻塞等理解的缺失,例如
@PostConstruct阻塞导致上下文启动超时、prototype Bean 资源未释放导致连接池耗尽等。 - 作用域影响:singleton Bean 在容器刷新时走完完整生命周期,并由容器负责销毁;prototype Bean 每次获取时经历创建和初始化,但销毁回调不受容器管理,必须手动释放资源。
下面是本文的组织架构图,它描绘了 Bean 生命周期的全貌以及关键的级联效应路径。
flowchart TD
subgraph 概念建立
M1[模块1: 生命周期全景概览]
M2[模块2: 从BeanDefinition到实例化前夕]
end
subgraph 机制拆解
M3[模块3: 实例化前后拦截]
M4[模块4: 实例化]
M5[模块5: 属性填充]
M6[模块6: Aware回调序列]
M7[模块7: BeanPostProcessor前后置处理]
M8[模块8: 初始化]
M9[模块9: 就绪与销毁]
end
subgraph 实战升华
M10[模块10: 生产事故排查专题]
Demo[Demo 代码示例]
end
subgraph 总结与面试
M11[模块11: 面试高频专题]
速查表[附录: 调用链速查表]
end
M1 --> M2 --> M3 --> M4 --> M5 --> M6 --> M7 --> M8 --> M9
M9 --> M10 --> Demo
M10 --> M11 --> 速查表
图表说明:
- 主旨概括:全景图突出了 Bean 从定义注册到销毁的单向流水线,以及一个致命但容易被忽视的短路路径——
resolveBeforeInstantiation提前返回代理,直接跳过属性填充和初始化阶段。 - 逐层分解:首先容器完成
BeanDefinition加载;在finishBeanFactoryInitialization触发实例化前,Spring 会询问所有InstantiationAwareBeanPostProcessor是否提前返回代理;若返回非空则立刻跳到就绪,完全跳过createBeanInstance、populateBean、initializeBean;否则严格按实例化→属性填充→Aware→初始化前后→就绪→销毁执行。 - 设计原理映射:Spring 采用模板方法模式固定了
doCreateBean的骨架,并在关键节点插入扩展点。级联效应:一旦postProcessBeforeInstantiation返回代理对象,Spring 认为该 Bean 已完全创建,后续依赖注入和初始化回调全部省略,极易造成 Bean 状态残缺。 - 工程实现与关键结论:理解这条不可逆的流水线是诊断 Bean 创建异常的基础。任何在
resolveBeforeInstantiation中返回自定义代理的行为,都必须自行处理依赖注入;在@PostConstruct中调用需要 AOP 代理的方法会失效,因为代理尚未创建。这些细节在生产环境屡次酿成事故。
1. Bean 生命周期的全景概览
当 AbstractApplicationContext.refresh() 执行至 finishBeanFactoryInitialization(beanFactory) 时,所有非懒加载的 singleton Bean 将被预实例化。这些 Bean 必须严格穿越一条由 Spring 容器编排的、包含 12 个阶段的单向流水线。每个阶段都预置了扩展点或回调插槽,而某些阶段的决策将不可逆地改变下游所有步骤的行为——这种 阶段间耦合效应 正是生产环境中 Bean 状态异常的核心根源。
1.1 十二阶段总览
下表不仅列出了每个阶段的名称和核心动作,更从 输入/输出状态 和 级联影响 两个维度给出了完整的认知坐标——前者回答“这个阶段开始时 Bean 是什么状态,结束后变成了什么状态”,后者回答“这个阶段的决策如何影响下游”。
| 阶段 | 核心动作 | 扩展点 / 回调接口 | 输入状态 | 输出状态 | 级联影响 / 备注 |
|---|---|---|---|---|---|
| ① 注册 | BeanDefinition 的加载、合并与缓存 | BeanFactoryPostProcessor.postProcessBeanFactory | 原始配置元信息(XML / 注解) | 合并后的 RootBeanDefinition | 修改 BeanDefinition 会影响后续所有阶段(第一篇详述) |
| ② 实例化前拦截 | 调用 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation | InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation | 只有 Class 对象,尚无 Bean 实例 | 若返回非空对象,则直接作为最终 Bean;否则继续 | 返回非空 → 跳过 ③~⑧,依赖注入与初始化全部失效 |
| ③ 实例化 | 通过构造器或工厂方法创建原始 Java 对象 | SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors | BeanClass 已确定,但无实例 | 原始对象实例,所有字段为 null | 选择的构造器会影响后续注入方式 |
| ④ 实例化后拦截 | 判断是否终止属性填充 | InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation | 原始对象实例 | 若无终止则进入属性填充,否则跳过 | 返回 false → 跳过 ⑤,@Autowired 全部失效 |
| ⑤ 属性填充 | 解析 @Autowired、@Value 等并注入依赖 | AutowiredAnnotationBeanPostProcessor.postProcessProperties | 原始对象,字段为 null | 依赖已注入,Bean 的业务引用已就绪 | 属性值的修改将直接影响后续初始化逻辑 |
| ⑥ Aware 回调 | 回调 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware | 这三个 Aware 接口 | 属性填充完成 | Bean 感知到名称、类加载器、工厂 | ApplicationContextAware 等不在此处回调,由后续阶段处理 |
| ⑦ 前置处理 | 调用 BeanPostProcessor.postProcessBeforeInitialization,完成剩余 Aware 回调并执行 @PostConstruct | ApplicationContextAwareProcessor、CommonAnnotationBeanPostProcessor | Bean 依赖已就绪,但未执行自定义初始化 | @PostConstruct 执行完毕,Aware 回调全部完成 | 此时 AOP 代理未创建,调用自身带切面的方法将失效 |
| ⑧ 初始化 | 调用 InitializingBean.afterPropertiesSet() 和自定义 init-method | InitializingBean、<bean init-method="..."> | 已完成前置处理 | 用户自定义初始化逻辑执行完毕 | 依赖外部未就绪 Bean 可能触发 NPE;与⑦的顺序固定 |
| ⑨ 后置处理 | 调用 BeanPostProcessor.postProcessAfterInitialization,创建 AOP 代理 | AbstractAutoProxyCreator | 初始化完成,原始对象 | 若需要,返回 AOP 代理对象替代原始对象 | 此后容器持有的 Bean 引用可能被代理替换 |
| ⑩ 就绪 | Bean 可供业务代码获取,触发 SmartInitializingSingleton 回调 | SmartInitializingSingleton.afterSingletonsInstantiated | 所有单例均已走完 ⑨ | Bean 完全可用,所有单例就绪 | 可在此安全执行依赖其他 Bean 的启动后检查 |
| ⑪ 容器关闭 | 发布 ContextClosedEvent,触发销毁流程 | 无用户扩展点 | 容器正在关闭 | 触发所有 singleton 的销毁逻辑 | — |
| ⑫ 销毁 | 依次执行 @PreDestroy、DisposableBean.destroy()、destroy-method | DestructionAwareBeanPostProcessor(处理 @PreDestroy)、DisposableBean | Bean 仍存在,即将被回收 | 资源释放,Bean 生命周期结束 | prototype Bean 的销毁回调不自动执行,需手动管理 |
1.2 Bean 生命周期全景流程图与扩展点解析
以下流程图以 颜色区分节点性质:
- 浅橙色:扩展点节点(内置
BeanPostProcessor子接口) - 浅绿色:回调节点(Aware、
InitializingBean、DisposableBean等) - 浅灰色:普通阶段节点
- 深橙色:级联短路节点(会直接跳过后续大段流程)
- 红色:级联效应导致的最终异常后果
flowchart TD
A["① 注册<br/>BeanDefinition"]
B["② 实例化前拦截<br/>【扩展点】InstantiationAwareBeanPostProcessor<br/>.postProcessBeforeInstantiation"]
C["③ 实例化<br/>【扩展点】SmartInstantiationAwareBeanPostProcessor<br/>.determineCandidateConstructors"]
D["④ 实例化后拦截<br/>【扩展点】InstantiationAwareBeanPostProcessor<br/>.postProcessAfterInstantiation"]
E["⑤ 属性填充<br/>【扩展点】AutowiredAnnotationBeanPostProcessor<br/>.postProcessProperties"]
F["⑥ Aware 回调<br/>【回调】BeanNameAware / BeanClassLoaderAware<br/>BeanFactoryAware"]
G["⑦ 前置处理<br/>【扩展点】BeanPostProcessor<br/>.postProcessBeforeInitialization<br/>(含 ApplicationContextAwareProcessor、<br/>CommonAnnotationBeanPostProcessor)"]
H["⑧ 初始化<br/>【回调】InitializingBean.afterPropertiesSet<br/>+ 自定义 init-method"]
I["⑨ 后置处理<br/>【扩展点】AbstractAutoProxyCreator<br/>.postProcessAfterInitialization"]
J["⑩ 就绪<br/>【回调】SmartInitializingSingleton<br/>.afterSingletonsInstantiated"]
K["⑪ 关闭"]
L["⑫ 销毁<br/>【回调】@PreDestroy / DisposableBean<br/>/ destroy-method"]
A --> B
B -- "返回 null(正常流程)" --> C
B -- "返回非空代理" --> SHORTCUT["⚡ 短路:跳过 ③~⑨"]
C --> D
D -- "返回 false" --> SKIP["跳过 ⑤ 属性填充"]
D -- "继续" --> E
E --> F
SKIP --> F
F --> G
G --> H
H --> I
I --> J
J --> K
K --> L
SHORTCUT -.->|"级联效应:依赖注入缺失,初始化未执行"| BUG["⚠ 生产事故:字段为 null / 状态不完整"]
style B fill:#ffe0b2,stroke:#ff9800,stroke-width:2px
style C fill:#ffe0b2,stroke:#ff9800,stroke-width:2px
style D fill:#ffe0b2,stroke:#ff9800,stroke-width:2px
style E fill:#ffe0b2,stroke:#ff9800,stroke-width:2px
style G fill:#ffe0b2,stroke:#ff9800,stroke-width:2px
style I fill:#ffe0b2,stroke:#ff9800,stroke-width:2px
style F fill:#dcedc8,stroke:#689f38,stroke-width:2px
style H fill:#dcedc8,stroke:#689f38,stroke-width:2px
style J fill:#dcedc8,stroke:#689f38,stroke-width:2px
style L fill:#dcedc8,stroke:#689f38,stroke-width:2px
style A fill:#f5f5f5,stroke:#9e9e9e,stroke-width:1px
style K fill:#f5f5f5,stroke:#9e9e9e,stroke-width:1px
style SHORTCUT fill:#ff9800,stroke:#333,stroke-width:2px,color:#fff
style BUG fill:#e57373,stroke:#b71c1c,stroke-width:2px,color:#fff
style SKIP fill:#e0e0e0,stroke:#757575,stroke-width:1px
阶段-扩展点/回调对照表
下表与流程图一一对应,并在 类型 列注明该阶段属于 扩展点 还是 回调,同时补充了典型实现与级联影响。
| 阶段 | 类型 | 关键接口 / 注解 | 典型实现类 | 级联影响 |
|---|---|---|---|---|
| ② 实例化前拦截 | 扩展点 | InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation | 自定义处理器 | 返回非空 → 跳过 ③~⑨,依赖注入与初始化全部失效 |
| ③ 实例化 | 扩展点 | SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors | AutowiredAnnotationBeanPostProcessor | 指定的构造器将影响后续注入和代理创建 |
| ④ 实例化后拦截 | 扩展点 | InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation | 自定义处理器 | 返回 false → 跳过 ⑤,@Autowired 等注入全部终止 |
| ⑤ 属性填充 | 扩展点 | InstantiationAwareBeanPostProcessor.postProcessProperties | AutowiredAnnotationBeanPostProcessor | 修改 PropertyValues 将改变实际注入值 |
| ⑥ Aware 回调 | 回调 | BeanNameAware, BeanClassLoaderAware, BeanFactoryAware | — | 无级联影响 |
| ⑦ 前置处理 | 扩展点 | BeanPostProcessor.postProcessBeforeInitialization | ApplicationContextAwareProcessor, CommonAnnotationBeanPostProcessor | 此时 AOP 代理未创建;调用需代理的方法导致注解失效 |
| ⑧ 初始化 | 回调 | InitializingBean.afterPropertiesSet, init-method | — | 依赖未就绪 Bean 可能触发 NPE |
| ⑨ 后置处理 | 扩展点 | BeanPostProcessor.postProcessAfterInitialization | AbstractAutoProxyCreator | 返回代理对象后,原始 Bean 引用被替换 |
| ⑩ 就绪 | 回调 | SmartInitializingSingleton.afterSingletonsInstantiated | — | 所有单例就绪,安全执行跨 Bean 操作 |
| ⑫ 销毁 | 回调 | @PreDestroy, DisposableBean.destroy, destroy-method | InitDestroyAnnotationBeanPostProcessor | prototype Bean 不自动进入此阶段 |
级联效应深度解析
上图中共有三条值得警惕的级联路径,它们均由 上游扩展点的早期返回或终止信号 触发,并遵循 模板方法模式的单向不可逆性 向下传递。
路径一:实例化前短路(阶段② → ⑩)
触发机制:
AbstractAutowireCapableBeanFactory.createBean() 在执行 doCreateBean() 之前调用 resolveBeforeInstantiation()。该方法遍历所有 InstantiationAwareBeanPostProcessor 并执行 postProcessBeforeInstantiation(beanClass, beanName)。若任一处理器返回非 null 对象,Spring 将直接应用 postProcessAfterInitialization(仅后置处理)并返回该对象,完全绕过 doCreateBean 及其内部的所有阶段(③~⑧)。
被跳过的阶段:实例化、属性填充、Aware 回调、前置处理、初始化。
直接后果:返回的对象没有经历依赖注入,所有 @Autowired、@Value 字段均为 null;@PostConstruct、afterPropertiesSet 不会执行,内部状态未初始化。
典型事故:自定义处理器提前返回了一个原始对象或未注入依赖的代理,业务调用时抛出 NullPointerException。案例见模块 10 案例四。
路径二:属性填充终止(阶段④ → ⑥)
触发机制:
populateBean() 在执行属性赋值前先调用 postProcessAfterInstantiation()。若返回 false,populateBean 立即返回,后续的 postProcessProperties 和 applyPropertyValues 均被跳过。
被跳过的阶段:仅 ⑤ 属性填充。
直接后果:Bean 的依赖字段保持为 null,但 Aware 回调和初始化流程仍会执行。afterPropertiesSet 内若校验依赖将抛出 NPE。
典型事故:配置了自定义 InstantiationAwareBeanPostProcessor 以禁止某些 Bean 的自动注入,但未处理好默认值,导致后续逻辑 NPE。
路径三:AOP 代理创建滞后(阶段⑦ → ⑨ 时序错位)
触发机制:
@PostConstruct 方法在 CommonAnnotationBeanPostProcessor.postProcessBeforeInitialization 中被反射调用,属于阶段⑦,而 AOP 代理的创建位于阶段⑨的 AbstractAutoProxyCreator.postProcessAfterInitialization。这意味着在 @PostConstruct 内部,this 引用仍然是原始对象,与容器最终暴露的代理对象不是同一个实例。
直接后果:在 @PostConstruct 中调用自身任何带有 @Async、@Transactional、@Cacheable 等需要 AOP 代理的方法时,目标方法将在原始对象上直接执行,注解切面完全失效。
典型事故:订单服务在 @PostConstruct 中调用 @Async 数据加载方法,结果同步阻塞启动,且高并发下因未走线程池而超时。案例见模块 10 案例一。
这三条级联路径的共同特征在于:容器按照预设模板执行流程,早期扩展点的特殊返回值会被当作“流程终止信号”,后续步骤不再具有执行机会。理解这一特征,是诊断 Bean 创建异常的核心思维模型。
2. 从 BeanDefinition 到实例化前夕
当所有 BeanDefinition 注册完毕后,容器刷新的关键一步 finishBeanFactoryInitialization 负责触发非懒加载 singleton Bean 的预实例化。这一步最终委托给 DefaultListableBeanFactory.preInstantiateSingletons():
// DefaultListableBeanFactory.preInstantiateSingletons()
public void preInstantiateSingletons() throws BeansException {
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
// ... 处理 FactoryBean
} else {
getBean(beanName); // 触发 Bean 创建
}
}
}
}
getBean 会经过一系列委托,最终进入 AbstractAutowireCapableBeanFactory.createBean()。在 createBean 的最前端,Spring 预留了一个决定性的分支——resolveBeforeInstantiation。不过,这一关键扩展点的详细剖析我们留给模块 3(实例化前后拦截),因为它和 postProcessAfterInstantiation 共同组成了 InstantiationAwareBeanPostProcessor 的两大拦截机制。这里只需记住:在真正走 doCreateBean 之前,容器会询问所有 InstantiationAwareBeanPostProcessor 是否要提前返回代理,一旦返回非空,后续全部流程都将被短路。
3. 实例化前后的拦截机制
在生命周期全景图的②(实例化前拦截)和④(实例化后拦截)两个节点上,Spring 通过 InstantiationAwareBeanPostProcessor 接口赋予了开发者两次极其强大的干预机会:一次在原始对象尚未创建时,可以直接返回一个替代对象并短路全部后续流程;另一次在对象刚刚创建、尚未填充属性时,可以立即终止依赖注入。这两处扩展点虽然隶属于同一个接口,但触发时机截然不同,造成的级联效应也各有侧重。
3.1 InstantiationAwareBeanPostProcessor 接口总览
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
// 实例化前回调:可在 Bean 实例化之前返回一个代理对象
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
// 实例化后回调:在实例化之后、属性填充之前执行,返回 false 则停止属性填充
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
// 属性填充时的回调:用于处理属性值(例如 @Autowired 解析)
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
return null;
}
}
前两个方法分别对应生命周期阶段②和④,正是本章的重点。它们都设计为 default 方法,默认返回 null 和 true,即不做任何拦截。只有子类覆写后,才能改变流程走向。
3.2 实例化前拦截:postProcessBeforeInstantiation
调用入口与短路源码
在 AbstractAutowireCapableBeanFactory.createBean() 中,首先会调用 resolveBeforeInstantiation,其内部逻辑极为关键:
// AbstractAutowireCapableBeanFactory.resolveBeforeInstantiation()
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
解读:
- 只有当
beforeInstantiationResolved不为false(即之前未被解析过)时才会进入逻辑。 - 调用
applyBeanPostProcessorsBeforeInstantiation遍历所有InstantiationAwareBeanPostProcessor并执行postProcessBeforeInstantiation(beanClass, beanName)。 - 如果任意处理器返回非
null对象,该对象就被当作最终的 Bean 返回,并且再执行一次BeanPostProcessor的后置处理(postProcessAfterInitialization),但完全跳过了doCreateBean中的实例化、填充、初始化等步骤。 - 该行为会被标记到
beforeInstantiationResolved = true,防止重复解析。
createBean 方法中紧接着判断:
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean; // 直接返回,跳过 doCreateBean
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
短路的级联效应
一旦 postProcessBeforeInstantiation 返回非空对象,以下阶段会被全部跳过:
- ③ 实例化 (
createBeanInstance) - ④ 实例化后拦截 (
postProcessAfterInstantiation) - ⑤ 属性填充 (
populateBean) - ⑥ Aware 回调
- ⑦ 前置处理与
@PostConstruct - ⑧ 初始化 (
afterPropertiesSet+init-method)
只保留一次后置处理(可能再创建代理),但原始的依赖注入和用户初始化逻辑永远不会执行。这是 Spring 生命周期中影响范围最大的级联效应。
在生产中,如果自定义处理器在此处返回了一个未经依赖注入的对象,就会导致 @Autowired 字段全为 null,这正是模块 10 案例四的根因。
3.3 实例化后拦截:postProcessAfterInstantiation
调用入口与终止源码
postProcessAfterInstantiation 在 populateBean 的初始阶段被调用,位于所有属性赋值之前:
// AbstractAutowireCapableBeanFactory.populateBean() 片段
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// ...
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return; // 直接返回,跳过后续的属性填充
}
}
}
}
// 后续才会处理 @Autowired 和 applyPropertyValues...
}
解读:
- 在
populateBean内部,首先遍历所有InstantiationAwareBeanPostProcessor,调用postProcessAfterInstantiation。 - 一旦任意一个处理器返回
false,populateBean方法立即return,跳过后面的postProcessProperties(@Autowired处理)和applyPropertyValues(显式属性赋值)。 - 但
populateBean的提前返回不会影响后续的 Aware、初始化等流程——它们仍然在initializeBean中照常执行。
级联效应:可控的依赖注入终止
此处的级联影响相对局部:只有阶段⑤属性填充被跳过,其余阶段⑥~⑨不受影响。这意味着:
- 字段上的
@Autowired、@Value不会被注入,保留为null。 - 如果 Bean 实现了
InitializingBean,其afterPropertiesSet中若校验这些字段,会直接抛NullPointerException。 - 可被用作一种“保护策略”:当不希望 Spring 自动注入某些字段时,通过该扩展点显式禁掉。
3.4 两种拦截的对比与定位
| 对比维度 | 实例化前拦截(阶段②) | 实例化后拦截(阶段④) |
|---|---|---|
| 触发方法 | postProcessBeforeInstantiation | postProcessAfterInstantiation |
| 触发时机 | Bean 实例化之前 | Bean 实例化之后,属性填充之前 |
| 入参 | 只有 Class<?> 和 beanName,尚无对象 | 已有原始对象实例 |
| 返回值含义 | 返回非空 → 短路全过程 | 返回 false → 终止属性填充 |
| 跳过的阶段 | ③~⑧ 全部跳过 | 仅跳过⑤ |
| 后续流程 | 直接进入 postProcessAfterInitialization | 继续 Aware、@PostConstruct、初始化等 |
| 主要风险 | 返回的对象未注入依赖,状态残缺 | 依赖缺失,但初始化逻辑仍会执行 |
理解这两者的边界非常重要:实例化前拦截更“暴力”,它会直接阻止 Bean 正常出生;实例化后拦截则是一次“精准手术”,只切断注入通道,让 Bean 以“无依赖”状态继续走完后续流程。
4. 实例化:从 Class 到原始对象
在通过所有短路检查后,正常流程进入了 doCreateBean 的第一步:createBeanInstance。此时,容器手中只有一个 BeanDefinition 和确定好的 Class,需要创造一个 Java 对象。
// AbstractAutowireCapableBeanFactory.createBeanInstance()
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 1. 工厂方法
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 2. 构造器选择(SmartInstantiationAwareBeanPostProcessor 可干预)
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// 3. 默认无参构造
return instantiateBean(beanName, mbd);
}
扩展点:SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors 可以返回候选构造器数组,从而干预构造器选择。实例化完成后,Bean 以原始对象的形式存在于 BeanWrapper 中,但所有依赖均为 null,属性填充尚未开始。
5. 属性填充:依赖的注入
属性填充是将依赖注入 Bean 的过程(不深入依赖解析细节,仅说明在此阶段发生)。
// AbstractAutowireCapableBeanFactory.populateBean()
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// ... (已处理 postProcessAfterInstantiation,见模块3)
// 自动注入或显式属性赋值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
// 自动装配
}
// postProcessProperties:AutowiredAnnotationBeanPostProcessor 在此处理 @Autowired, @Value
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) return;
pvs = pvsToUse;
}
}
// 应用属性值
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
AutowiredAnnotationBeanPostProcessor 会在 postProcessProperties 中解析 @Autowired 和 @Value 并注入依赖。属性填充完成后,Bean 的业务依赖已满足(但循环依赖可能彼时还是早期引用,后续篇章详解)。
6. Aware 回调序列
在依赖注入完成之后、初始化正式开始之前,Spring 会让 Bean 感知到容器内的一些基础设施。
// AbstractAutowireCapableBeanFactory.invokeAwareMethods()
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
这三行顺序明确:BeanNameAware → BeanClassLoaderAware → BeanFactoryAware。
注意:ApplicationContextAware、EnvironmentAware 等更高级的 Aware 回调并不在这里,它们由 ApplicationContextAwareProcessor(一个 BeanPostProcessor)在 postProcessBeforeInitialization 阶段处理。
7. BeanPostProcessor 的前置与后置处理
BeanPostProcessor 是生命周期的核心扩展点,分为前置回调 postProcessBeforeInitialization 和后置回调 postProcessAfterInitialization。它们在 initializeBean 的骨架中执行:
// AbstractAutowireCapableBeanFactory.initializeBean()
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable ex) { ... }
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
- 前置处理:
applyBeanPostProcessorsBeforeInitialization中,ApplicationContextAwareProcessor完成剩余 Aware 回调,CommonAnnotationBeanPostProcessor执行@PostConstruct(order 为LOWEST_PRECEDENCE)。 - 后置处理:
applyBeanPostProcessorsAfterInitialization中,AbstractAutoProxyCreator检查并创建 AOP 代理。在此阶段之前,AOP 切面均未织入。
8. 初始化:三件套的顺序
初始化阶段有三种回调方式,执行顺序极其严格:
@PostConstruct注解方法 —— 由CommonAnnotationBeanPostProcessor在postProcessBeforeInitialization中触发,属于阶段⑦。InitializingBean.afterPropertiesSet()—— 在invokeInitMethods中直接调用。- 自定义
init-method—— 同样由invokeInitMethods反射调用。
// AbstractAutowireCapableBeanFactory.invokeInitMethods()
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
((InitializingBean) bean).afterPropertiesSet();
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
顺序总结:@PostConstruct → afterPropertiesSet() → init-method。
级联提醒:@PostConstruct 执行时 AOP 代理尚未创建(后置处理在后面),因此异步、事务等注解都会失效。
9. 就绪与销毁
初始化完成后,Bean 进入就绪状态,可供应用使用。另外,所有单例初始化完毕后还会触发 SmartInitializingSingleton.afterSingletonsInstantiated(),非常适合做启动后健康检查。
容器关闭时,Spring 会销毁所有 singleton Bean,销毁顺序:
@PreDestroy—— 由DestructionAwareBeanPostProcessor(InitDestroyAnnotationBeanPostProcessor)处理。DisposableBean.destroy()- 自定义
destroy-method
// DisposableBeanAdapter.destroy()
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {
((DisposableBean) bean).destroy();
}
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
}
关键结论:prototype Bean 的销毁回调不会自动触发,必须手动管理资源。
10. 生产事故排查专题
10.1 @PostConstruct 中调用 @Async 方法导致异步失效
事故现象:某订单系统在 @PostConstruct 中调用 @Async 预加载方法,却同步执行,阻塞启动。
排查思路:线程名始终为 main,怀疑代理未生效;在 ApplicationRunner 中测试异步正常。
根因分析:@PostConstruct 在阶段⑦(postProcessBeforeInitialization)执行,此时 AOP 代理尚未创建(阶段⑨),this 是原始对象,@Async 切面未织入。
解决方案:改用 ApplicationRunner 或 @EventListener(ContextRefreshedEvent.class) 触发异步逻辑。
最佳实践:绝对不在 @PostConstruct 或 afterPropertiesSet 中调用依赖 AOP 代理的方法。
10.2 afterPropertiesSet 依赖的 Bean 为 null 导致启动失败
事故现象:启动时 NPE,堆栈指向 afterPropertiesSet,其中访问的 @Autowired 字段为 null。
排查思路:存在循环依赖;检查依赖链发现间接循环。被依赖的 Bean 暴露了早期引用,自身状态可能不完整。
根因分析:循环依赖导致注入的是尚未完成初始化的早期引用,状态残缺。属性填充虽然在 afterPropertiesSet 之前,但循环依赖扰乱了正常顺序。
解决方案:消除循环依赖;使用 @DependsOn;或采用 ObjectProvider 延迟获取。
最佳实践:在初始化回调中只做本 Bean 内部校验,避免依赖未就绪的外部 Bean。
10.3 prototype Bean 实现 DisposableBean 但资源未释放
事故现象:服务运行一段时间后文件句柄耗尽(Too many open files)。
排查思路:prototype Bean 持有文件流,实现了 DisposableBean 并关闭流,但 destroy 从未调用。
根因分析:Spring 对 prototype Bean 只负责创建和初始化,容器不持有其引用,因此不会自动调用销毁回调。
解决方案:调用方手动调用 destroyBean;使用 DestructionAwareBeanPostProcessor;或采用对象池/重构为 singleton。
最佳实践:prototype Bean 应尽量避免持有需显式释放的资源,否则必须构建自定义的资源管理机制。
10.4 InstantiationAwareBeanPostProcessor 提前返回代理导致属性丢失(可选案例)
现象:某 Bean 的所有 @Autowired 字段均为 null。
排查思路:发现 doCreateBean 未被调用,resolveBeforeInstantiation 返回了代理。
根因分析:自定义处理器在 postProcessBeforeInstantiation 返回了非空对象,短路全流程,未注入依赖。
解决方案:在代理内部手动 autowireBean,或改用 postProcessAfterInitialization 创建代理。
最佳实践:谨慎使用短路功能,确保返回的对象具有完整状态。
11. 面试高频专题
(本模块与正文严格隔离,以下为22道经典面试题,每题含标准回答、追问和加分回答)
Q1: 详细描述 Spring Bean 的完整生命周期。
标准回答:12阶段:①注册 → ②实例化前拦截 → ③实例化 → ④实例化后拦截 → ⑤属性填充 → ⑥Aware回调 → ⑦前置处理(@PostConstruct) → ⑧初始化(afterPropertiesSet/init-method) → ⑨后置处理(AOP代理) → ⑩就绪 → ⑪关闭 → ⑫销毁(@PreDestroy/DisposableBean/destroy-method)。
追问:ApplicationContextAware 何时调用?(阶段⑦) 短路后会怎样?(跳过③~⑨)
加分回答:源码入口 AbstractAutowireCapableBeanFactory.doCreateBean()。
Q2: BeanPostProcessor 和 InitializingBean 的执行顺序?为什么这样设计?
标准回答:postProcessBeforeInitialization 在前,InitializingBean 在中间,postProcessAfterInitialization 在后。设计为装饰器模式,允许外部增强包裹内部初始化。
追问:如果 @PostConstruct 和 afterPropertiesSet 同时存在呢?
加分回答:@PostConstruct 在 CommonAnnotationBeanPostProcessor 前置处理中,早于 afterPropertiesSet。
Q3: @PostConstruct 和 InitializingBean.afterPropertiesSet 哪个先执行?源码依据?
标准回答:@PostConstruct 先执行。源码依据:initializeBean 中 applyBeanPostProcessorsBeforeInitialization 在 invokeInitMethods 之前,CommonAnnotationBeanPostProcessor 在这里处理 @PostConstruct,order 为 LOWEST_PRECEDENCE。
追问:如果 afterPropertiesSet 调用了 @Async 方法会怎样?
加分回答:仍然失效,因为 AOP 代理在 postProcessAfterInitialization 创建。
Q4: Bean 初始化过程中有哪些干预扩展点?分别在什么时机?
标准回答:② postProcessBeforeInstantiation 可短路;④ postProcessAfterInstantiation 可终止填充;⑦ postProcessBeforeInitialization 可修改 Bean(含@PostConstruct);⑨ postProcessAfterInitialization 可创建代理。
追问:哪些扩展点会影响其他 Bean?
加分回答:depends-on 会影响顺序,SmartInitializingSingleton 可访问所有单例。
Q5: InstantiationAwareBeanPostProcessor 和普通 BeanPostProcessor 的区别?短路点在哪?
标准回答:前者多了三个方法,分别对应实例化前后和属性处理;短路点在 postProcessBeforeInstantiation 返回非空对象。源码见 resolveBeforeInstantiation。
追问:短路后 initializeBean 还执行吗?
加分回答:不会,只执行 postProcessAfterInitialization,跳过 invokeInitMethods。
Q6: Spring 容器关闭时,Bean 的销毁顺序是怎样的?
标准回答:@PreDestroy(由 DestructionAwareBeanPostProcessor) → DisposableBean.destroy → 自定义 destroy-method。
追问:@PreDestroy 和 DisposableBean 可以同时存在吗?顺序会乱吗?
加分回答:可以,顺序固定。CommonAnnotationBeanPostProcessor 的父类实现 DestructionAwareBeanPostProcessor。
Q7: prototype Bean 的生命周期和 singleton 有何不同?销毁回调会生效吗?
标准回答:prototype 只经历创建、填充、初始化,容器不管理销毁。销毁回调不自动调用,需手动 destroyBean。
追问:如何批量释放 prototype 资源?
加分回答:自定义 Scope 或注册 DestructionCallback。
Q8: 什么是 Aware 接口?常见有哪些?ApplicationContextAware 在哪里处理?
标准回答:让 Bean 感知容器的接口。常见的有 BeanNameAware、BeanFactoryAware、ApplicationContextAware。前三者在 invokeAwareMethods (阶段⑥),后者在 ApplicationContextAwareProcessor 的 postProcessBeforeInitialization (阶段⑦)。
追问:自定义 Aware 需要什么?
加分回答:实现对应 BeanPostProcessor。
Q9: 在 @PostConstruct 中调用 @Async 方法会异步吗?为什么?
标准回答:不会,同步执行。根源在于 AOP 代理在阶段⑨创建,@PostConstruct 在阶段⑦。
追问:除了 @Async,还有哪些失效?
加分回答:@Transactional、@Cacheable 等所有基于 AOP 的注解。
Q10: 如何在不重启的情况下动态修改已创建 Bean 的属性?
标准回答:利用 @RefreshScope(Spring Cloud),或自定义 BeanPostProcessor 返回包装代理,代理内部动态获取配置。
追问:直接替换单例池中的对象有什么风险?
加分回答:并发可见性问题,需要处理同步。
Q11: BeanFactoryPostProcessor 和 BeanPostProcessor 的执行时机区别?
标准回答:BeanFactoryPostProcessor 在容器刷新阶段、实例化之前,修改 BeanDefinition;BeanPostProcessor 在实例化、初始化阶段。前者在 invokeBeanFactoryPostProcessors,后者在 registerBeanPostProcessors 之后。
追问:能否在 BeanFactoryPostProcessor 中注册新的 Bean?
加分回答:可以,通过 registry.registerBeanDefinition。
Q12: 同时使用 @PostConstruct、InitializingBean、init-method,执行顺序?
标准回答:@PostConstruct → afterPropertiesSet → init-method。源码在 initializeBean 顺序固定。
追问:如果 init-method 和 afterPropertiesSet 同名怎么办?
加分回答:Spring 会检测并跳过重复调用。
Q13: finishBeanFactoryInitialization 做了什么?
标准回答:预实例化所有非懒加载的 singleton Bean,调用 preInstantiateSingletons,触发 getBean 完成全生命周期。
追问:它前面有哪些重要步骤?
加分回答:invokeBeanFactoryPostProcessors 和 registerBeanPostProcessors。
Q14: 在所有 Bean 初始化完成后执行代码有哪些方式?
标准回答:SmartInitializingSingleton.afterSingletonsInstantiated、ContextRefreshedEvent 监听器、ApplicationRunner/CommandLineRunner。
追问:它们执行的顺序?
加分回答:afterSingletonsInstantiated → ContextRefreshedEvent → ApplicationRunner。
Q15: @DependsOn 在生命周期中如何生效?
标准回答:在 doGetBean 时检查 depends-on,优先递归创建依赖的 Bean。它只控制顺序,不能解决循环依赖。
追问:和 @Order 的区别?
加分回答:@Order 主要用于集合注入和切面顺序。
Q16: AOP 代理在哪个阶段创建?为什么选这个时机?
标准回答:阶段⑨ postProcessAfterInitialization。此时 Bean 已完全初始化,代理包装安全;若提前,目标对象状态可能不完整。
追问:循环依赖中的早期引用怎么代理?
加分回答:三级缓存 getEarlyBeanReference 会提前创建代理。
Q17: 什么是早期 Bean 引用?在哪个阶段产生?
标准回答:Bean 在实例化后、填充后,通过 addSingletonFactory 暴露的 ObjectFactory。在实例化后 populateBean 之前添加,用于循环依赖。
追问:为什么构造器注入不能解决循环依赖?
加分回答:因为构造器时需要依赖,但早期引用尚未生成。
Q18: prototype Bean 的 @PostConstruct 和 @PreDestroy 生效吗?
标准回答:@PostConstruct 每次 getBean 都执行;@PreDestroy 不自动执行,除非手动 destroyBean。
追问:如何让 prototype 自动销毁?
加分回答:自定义 Scope 实现。
Q19 (系统设计题): 设计 Bean 健康检查系统
标准回答:实现 SmartInitializingSingleton,在所有单例就绪后遍历检查;用 ConcurrentHashMap 存储状态;对于不健康 Bean 包装代理返回降级结果。考虑级联依赖,避免检查时触发懒加载。
追问:如何不阻塞启动?
加分回答:异步线程执行检查,代理初始返回 “unknown” 状态。
Q20 (系统设计题): 配置热更新方案设计
标准回答:自定义 Scope + 代理(ScopedProxyMode),监听配置变更,清除 Scope 缓存,重新 getBean。注意旧 Bean 销毁需调用 DisposableBean 释放资源,可结合 DestructionCallback。
追问:并发安全怎么保证?
加分回答:ReadWriteLock,或 CopyOnWrite 思想。
Q21: doCreateBean 方法的执行流程
标准回答:createBeanInstance → 应用 MergedBeanDefinitionPostProcessor → 提前暴露 singletonFactory → populateBean → initializeBean。initializeBean 内含 Aware、前置、初始化、后置。
追问:提前暴露的时机和原因?
加分回答:在 addSingletonFactory 之后,为了循环依赖。
Q22: afterPropertiesSet 执行过长怎么排查和优化?
标准回答:用 jstack 查看主线程阻塞在 invokeInitMethods;将耗时逻辑移到 @EventListener(ContextRefreshedEvent.class) 异步执行;使用 @DependsOn 避免阻塞其他 Bean。
追问:如果必须初始化完才能服务怎么办?
加分回答:利用 ApplicationRunner 或启动时健康检查等待就绪。
12. Demo 代码示例
生命周期顺序演示
@Component
public class LifecycleBean implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean {
@PostConstruct
public void postConstruct() { System.out.println("1. @PostConstruct"); }
@Override
public void afterPropertiesSet() { System.out.println("2. afterPropertiesSet"); }
@Bean(initMethod = "customInit", destroyMethod = "customDestroy")
public void customInit() { System.out.println("3. custom init-method"); }
@PreDestroy
public void preDestroy() { System.out.println("4. @PreDestroy"); }
@Override
public void destroy() { System.out.println("5. DisposableBean.destroy"); }
public void customDestroy() { System.out.println("6. custom destroy-method"); }
}
@PostConstruct 调用 @Async 失效与修复
// 失效版本
@Component
public class AsyncInPostConstruct {
@Async
public void asyncMethod() { System.out.println(Thread.currentThread().getName()); }
@PostConstruct
public void init() { asyncMethod(); } // 同步执行
}
// 修复版本
@Component
public class FixedLoader {
@Async
public void asyncMethod() { ... }
@EventListener(ContextRefreshedEvent.class)
public void onRefresh() { asyncMethod(); }
}
prototype 资源泄漏与手动销毁
@Component
@Scope("prototype")
public class PrototypeResource implements DisposableBean {
public void doWork() { }
@Override
public void destroy() { System.out.println("释放资源"); }
}
// 调用方手动销毁
@Component
public class User {
@Autowired private ApplicationContext ctx;
public void use() {
PrototypeResource res = ctx.getBean(PrototypeResource.class);
try { res.doWork(); } finally { ctx.getBeanFactory().destroyBean("prototypeResource", res); }
}
}
实例化前短路导致属性丢失
@Component
public class ShortcutProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
if (beanClass == VictimBean.class) {
return new VictimBean(); // 跳过填充,@Autowired 字段为 null
}
return null;
}
}
附录:Bean 生命周期调用链速查表
| 阶段 | 入口方法 | 扩展点 / 回调 | 典型实现类 | 级联效应 |
|---|---|---|---|---|
| ① 注册 | invokeBeanFactoryPostProcessors | BeanFactoryPostProcessor | ConfigurationClassPostProcessor | 修改定义影响全局 |
| ② 实例化前拦截 | resolveBeforeInstantiation | InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation | 自定义 | 返回非空跳过③~⑨ |
| ③ 实例化 | createBeanInstance | SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors | AutowiredAnnotationBeanPostProcessor | 选择构造器影响注入 |
| ④ 实例化后拦截 | populateBean 开头 | postProcessAfterInstantiation | 自定义 | 返回 false 跳过⑤ |
| ⑤ 属性填充 | populateBean | postProcessProperties | AutowiredAnnotationBeanPostProcessor | 实际注入依赖 |
| ⑥ Aware 回调 | invokeAwareMethods | BeanNameAware 等 | - | - |
| ⑦ 前置处理 | applyBeanPostProcessorsBeforeInitialization | BeanPostProcessor.postProcessBeforeInitialization | ApplicationContextAwareProcessor, CommonAnnotationBeanPostProcessor | AOP 未创建 |
| ⑧ 初始化 | invokeInitMethods | InitializingBean.afterPropertiesSet, init-method | - | 依赖未就绪可能 NPE |
| ⑨ 后置处理 | applyBeanPostProcessorsAfterInitialization | BeanPostProcessor.postProcessAfterInitialization | AbstractAutoProxyCreator | 创建 AOP 代理 |
| ⑩ 就绪 | afterSingletonsInstantiated | SmartInitializingSingleton.afterSingletonsInstantiated | - | 所有单例就绪 |
| ⑫ 销毁 | destroy | @PreDestroy, DisposableBean, destroy-method | InitDestroyAnnotationBeanPostProcessor | prototype 不自动销毁 |
延伸阅读
- 《Spring 揭秘》王福强 —— Bean 生命周期章节
- 《Expert One-on-One J2EE Development without EJB》Rod Johnson —— IoC 容器设计初衷
- Spring Framework 5.x 官方文档 “Container Extension Points”
- Spring 源码分析系列:《AbstractAutowireCapableBeanFactory 详解》
- 《Java 并发编程实战》Brian Goetz —— 与 Bean 生命周期中的可见性、线程安全相关