摘要:本文深入解析 Spring Bean 生命周期的 13 个核心步骤,从实例化、属性注入到初始化前后的 BeanPostProcessor 钩子机制。重点揭示了 AOP 代理在 postProcessAfterInitialization 阶段创建的底层原理,以及三级缓存解决循环依赖的关键设计。文章还对比了 BeanPostProcessor 与 BeanFactoryPostProcessor 的区别,并介绍了 @PostConstruct、SmartInitializingSingleton 等扩展钩子,帮助读者从源码层面掌握 Spring 容器的核心工作机制。

"Spring Bean 的生命周期是什么?"
这道题面试频率之高,几乎跟"HashMap 原理"一个级别。但你仔细回忆一下——大部分人的回答是不是就三句话:实例化、属性注入、初始化?
这没错,但你漏掉了一整层东西。
面试官真正想听的,是你知不知道BeanPostProcessor这个机制——它才是贯穿 Spring Bean 生命周期的灵魂。没有它,AOP 切不进去、事务管理跑不起来、@Autowired 根本不会工作。BeanPostProcessor 是在 Bean 初始化前后插入自定义逻辑的钩子,它的 intercept 能力是 Spring 所有扩展功能的基础。
今天就从头到尾过一遍 Spring Bean 的生命周期,每一阶段我告诉你源码在哪儿、做了什么、有什么用。
先把整体流程画出来

一个 Bean 从诞生到销毁,理论上经历五个阶段。但 Spring 在这五个阶段里嵌入了大量干预点。把干预点加上,实际的步骤是 13 步:
1. 实例化(反射创建对象)
2. 属性注入(设置各种属性值)
3. BeanNameAware.setBeanName()
4. BeanClassLoaderAware.setBeanClassLoader()
5. BeanFactoryAware.setBeanFactory()
6. BeanPostProcessor.postProcessBeforeInitialization()
7. InitializingBean.afterPropertiesSet()
8. 自定义 init-method
9. BeanPostProcessor.postProcessAfterInitialization() ← 🔥 AOP在这步
10. Bean 准备就绪,可以用了
…
11. DisposableBean.destroy()
12. 自定义 destroy-method
13. Bean 销毁
这里面最核心的是第 9 步——postProcessAfterInitialization()。AOP 的代理对象就是在这步创建的。Spring 的 AbstractAutoProxyCreator 实现了 BeanPostProcessor,在 postProcessAfterInitialization 里判断这个 Bean 是否需要代理——需要就创建代理对象替换原始 Bean。
如果你不理解 Bean 生命周期里有这个钩子,你永远想不通"为什么 @Transactional 在构造器里调用无效"——因为构造器在步骤 1 就执行完了,事务代理在步骤 9 才创建,构造器里当然拿不到代理对象。
第一步到第四步:从 class 到对象

Spring 容器启动时,AbstractApplicationContext.refresh() 方法被调用,这个方法有 13 个子步骤,Bean 的生命周期只是其中一环。
核心实现在 AbstractAutowireCapableBeanFactory.doCreateBean(),我把关键步骤拆出来:
// AbstractAutowireCapableBeanFactory.java — 核心流程(简化)
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) {
BeanWrapper instanceWrapper = null;
// 第一步:实例化
// 通过构造器反射创建对象实例
if (mbd.isSingleton()) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
// 第二步:早期暴露(解决循环依赖)
// 把半成品放入三级缓存 singletonFactories
// 这样别的 Bean 在循环依赖时可以拿到这个半成品
boolean earlySingletonExposure = mbd.isSingleton() &&
this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 第三步:属性注入
// @Autowired、@Resource、@Value 都在这里处理
populateBean(beanName, mbd, instanceWrapper);
// 第四步:初始化(包括 Aware → Before → init → After)
Object exposedObject = initializeBean(beanName, exposedObject, mbd);
return exposedObject;
}
注意 addSingletonFactory 这步——把未完成属性注入的半成品对象放入三级缓存。这是 Spring 解决构造器循环依赖的关键。虽然属性注入的循环依赖靠二级缓存就够了,但三级缓存的存在是因为 AOP 代理需要在初始化后才创建。如果不用三级缓存,循环依赖时 AOP 代理对象就没办法正确创建。
每行源码都有它的意义。createBeanInstance 会判断用哪个构造器——如果你有多个构造器,Spring 会选参数最多的那个(或者你明确标注了 @Autowired 的那个)。populateBean 不只是设值,还会执行 InstantiationAwareBeanPostProcessor 的自定义注入逻辑。你自定义注解注入也是在这步通过处理器实现的。
第五步到第九步:各种 Aware 接口
initializeBean() 的内部实现是这样的:
// AbstractAutowireCapableBeanFactory.java — 初始化阶段
protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
// 第五步:调用 Aware 接口
invokeAwareMethods(beanName, bean);
// 第六步:Before 处理器
Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
// 第七步 + 第八步:调用初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
// 第九步:After 处理器 ← AOP 代理在这里
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
}
invokeAwareMethods() 里执行的实际上是三个 Aware 的判断:
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(getBeanFactory());
}
}
}
只判断三个 Aware?等等——你不是说有十几个 Aware 吗?确实有:ApplicationContextAware、EnvironmentAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware 等等。但那些不是在 initializeBean() 里处理的——它们是在 ApplicationContextAwareProcessor(一个 BeanPostProcessor)的 postProcessBeforeInitialization 中处理的。也就是说,所有 ApplicationContext 相关的 Aware 是在第六步的 applyBeanPostProcessorsBeforeInitialization 中执行的,不是在第五步。
这给我们的教训是:Spring 把 Aware 分成了两类——容器核心 Aware(BeanName、BeanFactory 等)在 invokeAwareMethods 硬编码处理,应用上下文的 Aware 走 BeanPostProcessor 机制处理。这种分层设计说明了 Spring 源码的一个特点:能走扩展点走的,绝不硬编码。
顺便说一句,ApplicationContextAwareProcessor 本身就是一个内置的 BeanPostProcessor,它在 Spring 容器启动时由 refresh() 方法中的 prepareBeanFactory() 注册进去的。你在第六步的 postProcessBeforeInitialization 里能拿到 ApplicationContext,是因为这个处理器在 applyBeanPostProcessorsBeforeInitialization 遍历时执行了。这个过程对你来说是完全无感的——你只需要让你的 Bean 实现 ApplicationContextAware 接口,Spring 就会自动把 ApplicationContext 传进来。
再来看看第七步 invokeInitMethods 内部操作的顺序:
// 初始化方法调用顺序
protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd) {
// 先调 InitializingBean 接口
if (bean instanceof InitializingBean) {
((InitializingBean) bean).afterPropertiesSet();
}
// 再调自定义 init-method(XML 配置或 @Bean(initMethod=…))
if (mbd.getInitMethodName() != null) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
注意顺序:afterPropertiesSet 在前,自定义 init-method 在后。如果你的 Bean 同时实现了 InitializingBean 和配置了 init-method,afterPropertiesSet 会先执行。这个顺序在某些场景下很重要——比如你需要在 afterPropertiesSet 里验证所有必要属性已注入,然后在 init-method 里启动一些后台线程或订阅消息队列。
还有一个很多人忽略的细节:invokeCustomInitMethod 走的是反射,而且 Spring 会缓存这个 Method 对象,避免重复反射带来的性能开销。另外如果你的 init-method 的参数列表是 () 或者接收 (String, Object[]) 格式的,Spring 都能处理——但实际上大部分场景只需要无参方法。
第九步:AOP 代理就是在这里创建的
// AbstractAutoProxyCreator.java — 在 postProcessAfterInitialization 中创建代理
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
// 判断是否需要对当前 Bean 创建代理
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
wrapIfNecessary 做的事:
1. 获取当前 Bean 所有的 Advisor(切面)
2. 用 Pointcut 匹配 Bean 的方法
3. 如果匹配上,通过 DefaultAopProxyFactory 创建代理
4. 返回代理对象替换原始 Bean
这个替换是透明的——容器里的 Bean 关联已经变成了代理对象,后续注入到其他 Bean 里的也是这个代理。
但这里有一个大坑:postProcessAfterInitialization 不只是 AOP 在用。 Spring 内部有很多内置的 BeanPostProcessor:AutowiredAnnotationBeanPostProcessor(处理 @Autowired)、RequiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor(处理 @Resource、@PostConstruct)等等。每个 BeanPostProcessor 的 order 决定了它们的执行顺序,这直接影响了你的 Bean 最终被处理成什么样。
如果这些处理器的顺序错了(或者你自己注册的 BeanPostProcessor 优先级不对),就会出现"为什么我的 @Autowired 没生效"这类问题。
BeanPostProcessor 和 BeanFactoryPostProcessor 的区别
这个也是面试高频混淆点。
BeanFactoryPostProcessor:在 Bean 实例化之前执行,操作的是 BeanDefinition(Bean 的定义元数据)。你可以修改 Bean 的 scope、lazy-init 标记、属性值等。执行时机在 refresh() 的 invokeBeanFactoryPostProcessors() 阶段。
BeanPostProcessor:在 Bean 实例化之后、初始化前后执行,操作的是 Bean 实例本身。你可以包装、替换、代理 Bean。
简单记忆:前者改配置,后者改对象。
还有一个容易被忽略的点:BeanFactoryPostProcessor 本身不支持 @Order 注解来排序——你必须实现 PriorityOrdered 或 Ordered 接口来控制执行顺序。这一点跟 BeanPostProcessor 的行为不一致,面试官偶尔会拿这个来考察候选人对源码的熟悉程度。
Spring 还提供了哪些生命周期钩子?

除了上面的核心 13 步,还有几个面试官可能会问的钩子:
@PostConstruct / @PreDestroy:JSR-250 规范定义的初始化/销毁方法,在 CommonAnnotationBeanPostProcessor 中处理。@PostConstruct 在 postProcessBeforeInitialization 中执行(在 afterPropertiesSet 之前),@PreDestroy 在 destroy 阶段执行。
SmartInitializingSingleton:在所有单例 Bean 都初始化完成后触发。afterSingletonsInstantiated() 方法在所有 Bean 创建完毕后调用一次,适合做全局后置处理——比如启动后检查所有依赖是否就绪。
Lifecycle 接口:start() 和 stop() 方法,主要用于管理容器生命周期内的启动和停止行为。Spring 容器会在 refresh() 的最后调用 startBeans()——所有实现了 Lifecycle 的 Bean 会按依赖顺序启动。这在 Spring Cloud 或消息队列的场景下特别有用,比如确保连接池在消息监听器启动之前就绪。
SmartLifecycle:Lifecycle 的增强版,多了 getPhase() 控制启动顺序,以及 isAutoStartup() 判断是否自动启动。如果你的应用需要热加载某些组件,用 SmartLifecycle 比用 @EventListener(ContextRefreshedEvent.class) 更优雅。
🎯 面试官视角的标准回答
"Spring Bean 的完整生命周期分为 13 步:实例化(通过构造器反射创建对象,同时放入三级缓存解决循环依赖)、属性注入(处理 @Autowired、@Resource、@Value)、Aware 接口调用(BeanName、BeanClassLoader、BeanFactory 三个硬编码 + 其他通过 BeanPostProcessor)、BeanPostProcessor 的 Before 处理器(执行 @PostConstruct)、InitializingBean 的 afterPropertiesSet、自定义 init-method、BeanPostProcessor 的 After 处理器(AOP 代理就是在这步创建的,AbstractAutoProxyCreator 的 wrapIfNecessary 方法判断是否需要代理)、Bean 就绪、销毁阶段(@PreDestroy、DisposableBean.destroy、自定义 destroy-method)。核心理解:BeanPostProcessor 是 Spring 扩展功能的基石——没有它,AOP、事务、@Autowired 全部无法工作。区分 BeanFactoryPostProcessor(操作 BeanDefinition、在实例化前执行)和 BeanPostProcessor(操作 Bean 实例、在初始化前后执行)。有两个容易被忽略的钩子:SmartInitializingSingleton(所有单例都初始化后触发)和 SmartLifecycle(容器级别的 start/stop 管理)。"
下篇预告:面试官问线程池,大部分人只背了七个参数。下一篇文章聊 ThreadPoolExecutor 的核心源码——队列满了怎么办、拒绝策略怎么选、核心线程数到底设多少合适。
>
网硕互联帮助中心

评论前必须登录!
注册