共计 4554 个字符,预计需要花费 12 分钟才能阅读完成。
一、为什么要深入理解 Spring Bean 生命周期?
在日常 Spring 应用开发中,我们习惯性地通过 @Component
、@Service
、@Repository
等注解定义 Bean,通过 @Autowired
注入依赖,甚至可以借助 Spring Boot 自动装配毫不费力地构建出完整的业务系统。
但你是否曾遇到过以下问题:
- 为什么某些 Bean 的属性注入不到?
- 为什么我注册的
@PostConstruct
方法没有执行? - 如何在 Bean 创建前对其实例进行定制?
- 动态代理 Bean 生成是在什么时候发生的?
- Bean 的销毁方法为什么没有执行?
这些问题的根源,归结到 对 Spring Bean 生命周期的理解不够深入。Spring 是一个高度扩展性的框架,理解其生命周期,不仅有助于提升故障排查能力,还能为我们构建框架级别组件提供理论支撑。
二、Spring Bean 生命周期总览图
我们先通过一张流程图对整个生命周期有一个总体感知:

从中可以看出,Spring Bean 生命周期贯穿了 Bean 的整个创建、使用到销毁全过程。下面我们将逐个环节做深入解析,并结合源码剖析其执行逻辑。
三、Spring Bean 生命周期各阶段详解与源码解析
1. BeanDefinition 注册阶段(非实例化)
在 Spring 启动过程中,IOC 容器通过 BeanDefinitionReader
读取配置或扫描注解,将类元信息封装为 BeanDefinition
并注册进 BeanFactory。
AbstractApplicationContext.refresh() {
obtainFreshBeanFactory();
invokeBeanFactoryPostProcessors();
registerBeanPostProcessors();
}
其中:
BeanDefinition
只是描述信息,尚未创建对象;- 这是
@ComponentScan
、@Configuration
等注解生效的阶段; - 此时可通过
BeanFactoryPostProcessor
修改 Bean 的定义(如设置默认值、scope 等);
扩展点举例:
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) {
BeanDefinition bd = factory.getBeanDefinition("myBean");
bd.getPropertyValues().add("name", "overrideName");
}
}
2.实例化阶段(Instantiation)
Spring 通过反射调用构造器创建 Bean 对象,默认使用无参构造器,也支持构造函数注入(自动推断参数)。
源码入口:
AbstractAutowireCapableBeanFactory.createBeanInstance()
关键逻辑:
protected BeanWrapper createBeanInstance(...) {
// 1. 如果是 FactoryBean,则调用工厂方法
// 2. 如果有构造函数参数,尝试自动推导匹配
// 3. 默认使用无参构造函数进行反射创建实例
}
扩展点:
- 可通过
InstantiationAwareBeanPostProcessor
拦截实例化行为; - 如果你需要返回代理对象(比如提前暴露),也可以在此阶段介入
示例代码:
@Component
public class MyInstantiationProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
if (beanClass == MyService.class) {
return Proxy.newProxyInstance(...); // 返回代理对象
}
return null;
}
}
3.依赖注入阶段(Populate Bean)
完成对象创建后,Spring 会进行依赖注入,填充所有 @Autowired
、@Value
、@Resource
等注解的字段、setter 方法、构造函数。
源码入口:
AbstractAutowireCapableBeanFactory.populateBean()
依赖注入的实现依赖于 AutowiredAnnotationBeanPostProcessor
:
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
metadata.inject(bean, beanName, pvs);
注意事项:
- 注入在 实例化之后、初始化之前;
- 此阶段执行失败(如 Bean 不存在)将抛出
NoSuchBeanDefinitionException
; @Autowired(required = false)
可以避免强依赖。
4.Aware 接口回调
Spring 提供了多种 Aware
接口让 Bean 感知容器的上下文环境:
接口 | 描述 |
---|---|
BeanNameAware |
注入 Bean 的名称 |
BeanFactoryAware |
注入 BeanFactory |
ApplicationContextAware |
注入 ApplicationContext |
EnvironmentAware |
注入当前运行环境 |
执行逻辑:
invokeAwareMethods(beanName, bean);
调用顺序:
if (bean instanceof BeanNameAware) { bean.setBeanName(beanName); }
if (bean instanceof BeanFactoryAware) { bean.setBeanFactory(this); }
if (bean instanceof ApplicationContextAware) { bean.setApplicationContext(context); }
5.初始化前处理(BeanPostProcessor)
Spring 提供 BeanPostProcessor
接口允许我们在初始化前后对 Bean 做处理或代理。
初始化前处理:
applyBeanPostProcessorsBeforeInitialization()
此方法会遍历所有注册的 BeanPostProcessor
并调用:
Object postProcessBeforeInitialization(Object bean, String beanName);
使用场景:
- 校验 Bean 属性是否合法;
- 给 Bean 设置默认值;
- Bean 属性审计日志。
6.初始化阶段(InitializingBean、@PostConstruct、init-method)
这是 Bean 生命周期中最关键的一步。
Spring 提供了多种初始化回调方式,执行顺序如下:
① @PostConstruct
② InitializingBean.afterPropertiesSet()
③ init-method(配置文件或注解指定)
执行逻辑:
invokeInitMethods(beanName, bean, mbd);
示例:
@Component
public class MyBean implements InitializingBean {
@PostConstruct
public void postConstruct() {
System.out.println("PostConstruct 初始化...");
}
@Override
public void afterPropertiesSet() {
System.out.println("afterPropertiesSet 初始化...");
}
public void initMethod() {
System.out.println("init-method 初始化...");
}
}
在 Spring Boot 中,可以通过注解指定 initMethod:
@Bean(initMethod = "initMethod")
public MyBean myBean() {
return new MyBean();
}
7.初始化后处理(BeanPostProcessor#postProcessAfterInitialization)
此阶段非常重要,AOP 动态代理就在此发生。
源码入口:
applyBeanPostProcessorsAfterInitialization()
常见的代理类如:
InfrastructureAdvisorAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator
它们会判断当前 Bean 是否命中某个切面,然后通过 JDK / CGLIB 生成代理类。
你也可以实现自己的 BeanPostProcessor
,在这里对 Bean 做增强:
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof MyService) {
return ProxyFactory.createProxy(bean); // 返回代理类
}
return bean;
}
8.Bean 就绪(进入 IOC 容器)
此时的 Bean:
- 已完成初始化;
- 如果启用了 AOP,可能是代理对象;
- 加入了 Singleton 缓存;
- 可以被其他 Bean 注入、使用。
你可以通过 ApplicationContext.getBean()
获取此 Bean,或等待外部调用。
9.容器关闭阶段 & Bean 销毁
当 Spring 容器调用 close()
或触发 registerShutdownHook()
时,Spring 会执行销毁流程:
AbstractApplicationContext.close()
-> doClose()
-> destroyBeans()
Spring Boot 中指定 destroyMethod:
@Bean(destroyMethod = "customDestroy")
public MyBean myBean() {
return new MyBean();
}
四、总结:掌握生命周期的价值
理解 Spring Bean 生命周期并不仅仅是面试的加分项,它在实际开发中能带来多方面收益:
✅ 理解 Bean 的真正生命周期,避免开发中常见误区
✅ 自定义框架组件(如数据审计、通用监控)能力增强
✅ 为 AOP、事务、事件等高级特性提供认知基础
✅ 能基于生命周期开发通用框架级能力,如热更新、延迟加载等
五、关注后续专栏
本文是《Spring 源码解析系列》专栏的第 1 篇,后续将发布:
- 《@Transactional 源码深度解读与事务传播机制详解》
- 《Spring AOP 原理与 CGLIB / JDK 动态代理源码分析》
如果本文对你有帮助,欢迎点赞、评论、收藏!我是 李卷卷,专注Java相关知识输出。感谢阅读!