Spring Bean 的生命周期是怎么样的?
2026年02月01日
一则或许对你有用的小广告
欢迎 加入小哈的星球 ,你将获得: 专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新开坑项目: 《Spring AI 项目实战(问答机器人、RAG 增强检索、联网搜索)》 正在持续爆肝中,基于
Spring AI + Spring Boot3.x + JDK 21..., 点击查看; - 《从零手撸:仿小红书(微服务架构)》 已完结,基于
Spring Cloud Alibaba + Spring Boot3.x + JDK 17..., 点击查看项目介绍; 演示链接: http://116.62.199.48:7070/; - 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/
面试考察点
面试官抛出这个问题,通常想考察以下几个层面的理解:
- 对 Spring IoC 容器核心机制的理解深度:不仅要知道步骤,更要明白每个步骤存在的意义和底层原理。
- 实际应用与扩展能力:能否在生命周期中的正确节点(如
InitializingBean、@PostConstruct、BeanPostProcessor)进行自定义逻辑注入,解决实际问题。 - 知识体系的完整性:能否清晰地区分
BeanFactory和ApplicationContext在生命周期处理上的细微差别,以及不同作用域(如singleton、prototype)生命周期的不同。 - 问题排查与设计能力:当 Bean 的创建、依赖注入或销毁出现问题时,是否能根据生命周期流程快速定位。
核心答案
Spring Bean 的生命周期指的是一个 Bean 在 Spring IoC 容器中从被实例化、装配属性、初始化到最终被销毁的完整过程。其核心流程可以概括为四个大阶段和一系列扩展点:
- 实例化:容器通过反射(如构造器)或工厂方法创建 Bean 的实例。
- 属性赋值:为 Bean 注入依赖的属性(通过
setter、字段或构造器),并处理Aware接口回调。 - 初始化:执行各种初始化回调,使 Bean 达到可用状态。
- 销毁:在容器关闭时,执行预定义的销毁逻辑。
深度解析
原理/机制详解
1. 实例化与属性赋值
- 实例化:容器根据 Bean 定义(
BeanDefinition)选择合适的策略(如CglibSubclassingInstantiationStrategy)创建对象。此时对象只是一个 “空壳”,属性均为默认值。 - 属性赋值:此阶段核心是 依赖注入(DI)。容器解析
@Autowired、@Value、<property>等元数据,完成属性填充。Aware接口回调也发生在此阶段之后,目的是让 Bean 能感知到容器自身的一些基础设施对象(如BeanNameAware、BeanFactoryAware、ApplicationContextAware)。
2. 初始化——生命周期中的 “精加工” 这是最复杂且扩展性最强的阶段,包含多个有序的扩展点:
BeanPostProcessor初始化前:BeanPostProcessor是 Spring 提供的强大扩展接口。postProcessBeforeInitialization方法允许在 Bean 的任何自定义初始化方法被调用之前,对 Bean 进行修改或包装(例如,@Autowired注解的处理就是通过AutowiredAnnotationBeanPostProcessor完成的)。- 自定义初始化:按顺序执行:
@PostConstruct注解标注的方法(JSR-250 标准)。InitializingBean接口的afterPropertiesSet()方法。- 通过 XML 的
init-method属性或@Bean(initMethod = “…”)指定的方法。
BeanPostProcessor初始化后:在自定义初始化方法执行之后调用。这是 AOP 代理创建的关键时机。AbstractAutoProxyCreator等后置处理器会在此检查 Bean,如果需要被代理,则会返回一个代理对象,而不是原始 Bean。这也是为什么注入的 Bean 通常已经是代理对象的原因。
3. 销毁
与初始化对应,销毁阶段也有类似的回调顺序(仅对 singleton Bean 有效,prototype Bean 容器不管理其销毁):
@PreDestroy注解标注的方法。DisposableBean接口的destroy()方法。- 通过 XML 的
destroy-method属性或@Bean(destroyMethod = “…”)指定的方法。
代码示例
@Component
public class LifecycleDemoBean implements BeanNameAware, InitializingBean, DisposableBean {
private String beanName;
public LifecycleDemoBean() {
System.out.println("1. 构造器调用 -> 实例化");
}
@Autowired
public void setDependency(SomeService service) {
System.out.println("2. 依赖注入 (Autowired)");
}
@Override
public void setBeanName(String name) {
this.beanName = name;
System.out.println("3. Aware接口回调 (BeanNameAware)");
}
@PostConstruct
public void postConstruct() {
System.out.println("5. @PostConstruct 方法");
}
@Override
public void afterPropertiesSet() {
System.out.println("6. InitializingBean.afterPropertiesSet()");
}
public void customInit() {
System.out.println("7. 自定义 init-method");
}
@Override
@PreDestroy
public void destroy() {
System.out.println("9. @PreDestroy 方法(与DisposableBean.destroy()合并)");
}
public void customDestroy() {
System.out.println("10. 自定义 destroy-method");
}
}
// 定义一个 BeanPostProcessor
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
if (bean instanceof LifecycleDemoBean) {
System.out.println("4. BeanPostProcessor.postProcessBeforeInitialization");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof LifecycleDemoBean) {
System.out.println("8. BeanPostProcessor.postProcessAfterInitialization (AOP代理通常在此生成)");
}
return bean;
}
}
最佳实践与注意事项
- 推荐使用顺序:对于初始化,建议优先使用
@PostConstruct(标准,与框架解耦),其次是@Bean的initMethod,最后才是InitializingBean接口(将代码与 Spring 紧耦合)。销毁同理。 - 理解作用域影响:
singletonBean 会完整经历所有生命周期。prototypeBean 在容器只负责实例化、装配和初始化(到postProcessAfterInitialization为止),之后便将对象交给调用者,容器不再跟踪其生命周期,不会调用销毁方法。 BeanPostProcessor的威力与陷阱:它是全局性的,会应用到容器中所有 Bean,实现时务必通过bean的类型或beanName进行精确判断,避免无谓的性能开销和副作用。
常见误区
- 混淆“实例化”和“初始化”:认为
new出来的对象就是 Bean 了。实际上,未经过属性注入和初始化的对象,其功能是不完整的。 - 认为 AOP 代理在初始化后单独进行:AOP 代理其实是某个特定的
BeanPostProcessor(如AnnotationAwareAspectJAutoProxyCreator)在postProcessAfterInitialization阶段创建的,它是初始化流程的一部分。 - 忽略
ApplicationContext与BeanFactory的区别:ApplicationContext在容器启动时就会预先实例化所有非懒加载的单例 Bean,而基础的BeanFactory默认是延迟初始化的。
总结
Spring Bean 的生命周期是一个由 IoC 容器驱动、通过定义良好的步骤和丰富的扩展点构建的精密流程,其核心目标是实现控制反转与依赖注入,并通过 BeanPostProcessor 等机制提供了无与伦比的扩展灵活性。理解它,是编写高质量 Spring 应用和进行深度定制的基石。