Spring Bean 生命周期:从源码到实战
本文用「人话」讲解 Spring Bean 从创建到销毁的全过程,附带源码级扩展点解析。
# 先有一张地图
Spring Bean 的生命周期可粗分为三大阶段:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 实例化 │ → │ 属性填充 │ → │ 初始化 │
│ Instantiation│ │ Populate │ │ Initialize │
└─────────────┘ └─────────────┘ └─────────────┘
↓ ↓
创建对象(new) 投入使用
2
3
4
5
6
细分则包含 13个关键步骤,其中穿插 6个核心扩展点。读完本文,你将能回答:
@Autowired是在哪个阶段注入的?@PostConstruct和InitializingBean哪个先执行?- AOP 代理是在什么时候创建的?
# 第一阶段:Bean 的生成(13步)
# 步骤1:扫描并生成 BeanDefinition
Spring 启动时,会扫描 @ComponentScan 指定包下的所有 .class 文件。
关键技术点:
- 使用 ASM 技术解析字节码(不加载类到 JVM,速度快)
- 将类信息包装为
BeanDefinition对象(Bean 的「设计图纸」)
// BeanDefinition 核心属性
public interface BeanDefinition extends AttributeAccessor {
String getBeanClassName(); // 类名(注意:是字符串,不是 Class 对象)
String getScope(); // singleton / prototype
boolean isLazyInit(); // 是否懒加载
String getInitMethodName(); // 初始化方法
String getDestroyMethodName(); // 销毁方法
}
2
3
4
5
6
7
8
# 步骤2:合并 BeanDefinition(父子继承)
Spring 支持 XML 形式的父子 Bean 定义:
<bean id="parent" class="com.example.Parent" scope="prototype"/>
<bean id="child" class="com.example.Child" parent="parent"/>
2
child 会继承 parent 的属性(如 scope)。合并后生成新的 RootBeanDefinition。
💡 实际开发中:注解方式很少用父子 Bean,但 Spring 内部(如配置类处理)会用到此机制。
# 步骤3:加载类
将 BeanDefinition 中的类名字符串,通过类加载器转为 Class<?> 对象。
// AbstractBeanFactory.doGetBean() 中的类加载逻辑
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
2
# 🔧 扩展点1:实例化前干预
接口:InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
作用:在对象创建前,给你一个「偷梁换柱」的机会。
@Component
public class MyProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
if ("userService".equals(beanName)) {
// 直接返回自定义对象,Spring 就不会实例化了!
return new UserService("直接new的对象");
}
return null; // 返回 null,Spring 继续正常流程
}
}
2
3
4
5
6
7
8
9
10
11
⚠️ 注意:若此处返回非空对象,会跳过依赖注入和大部分后续步骤,直接进入「初始化后」步骤。
# 步骤4:实例化(创建对象)
Spring 创建 Bean 对象的三种方式:
| 方式 | 示例 | 优先级 |
|---|---|---|
| Supplier | beanDefinition.setInstanceSupplier(() -> new UserService()) | 最高 |
| 工厂方法 | @Bean 或 factory-method | 次之 |
| 构造方法 | new UserService() | 默认 |
构造方法推断逻辑:
- 只有默认无参构造 → 用它
- 只有一个有参构造 → 用它
- 多个构造方法 → 报错(除非用
@Autowired指定)
@Component
public class UserService {
// 这个会被自动选为构造方法
public UserService(OrderService orderService) {
this.orderService = orderService;
}
}
2
3
4
5
6
7
# 🔧 扩展点2:BeanDefinition 后置处理
接口:MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()
作用:实例化后、属性赋值前,修改 BeanDefinition。
@Component
public class MyMergedProcessor implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,
Class<?> beanType, String beanName) {
if ("userService".equals(beanName)) {
// 手动添加一个属性值(相当于 XML 的 <property>)
beanDefinition.getPropertyValues().add("orderService", new OrderService());
}
}
}
2
3
4
5
6
7
8
9
10
11
# 🔧 扩展点3:实例化后处理
接口:InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
作用:对象已创建,但还未填充属性。可在这里提前做些初始化。
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
if ("userService".equals(beanName)) {
UserService userService = (UserService) bean;
userService.preInit(); // 自定义预初始化
}
return true; // 返回 true 继续流程,false 则跳过属性填充
}
2
3
4
5
6
7
8
# 步骤5-6:自动注入与属性处理
Spring 在此阶段处理:
@Autowired/@Value(Spring 原生)@Resource(JSR-250 标准)
底层实现:通过 InstantiationAwareBeanPostProcessor.postProcessProperties() 扩展点完成。
// AutowiredAnnotationBeanPostProcessor 的核心逻辑
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
// 1. 找出所有带 @Autowired 的字段/方法
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
// 2. 注入值
metadata.inject(bean, beanName, pvs);
return pvs;
}
2
3
4
5
6
7
8
# 🔧 扩展点4:Aware 接口回调
属性填充完成后,Spring 会向 Bean 「汇报」一些上下文信息:
| Aware 接口 | 注入内容 |
|---|---|
BeanNameAware | Bean 的名称 |
BeanClassLoaderAware | 类加载器 |
BeanFactoryAware | BeanFactory 容器 |
@Component
public class UserService implements BeanNameAware, ApplicationContextAware {
private String beanName;
private ApplicationContext context;
@Override
public void setBeanName(String name) {
this.beanName = name; // 回调注入
}
@Override
public void setApplicationContext(ApplicationContext ctx) {
this.context = ctx; // 回调注入
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
💡 ApplicationContextAware 是在「初始化前」阶段通过
ApplicationContextAwareProcessor注入的。
# 🔧 扩展点5:初始化前处理
接口:BeanPostProcessor.postProcessBeforeInitialization()
核心作用:
- 执行
@PostConstruct注解的方法(通过InitDestroyAnnotationBeanPostProcessor) - 执行更多 Aware 回调(Environment、ResourceLoader 等)
@Component
public class UserService {
@PostConstruct
public void init() {
// 依赖注入完成后执行
System.out.println("初始化中...");
}
}
2
3
4
5
6
7
8
# 步骤7:初始化
Spring 提供两种初始化方式(按顺序执行):
InitializingBean.afterPropertiesSet()- 自定义 init-method(如
@Bean(initMethod = "init"))
@Component
public class UserService implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
// 校验必填属性、开启资源等
System.out.println("属性已设置完成,执行初始化逻辑");
}
}
2
3
4
5
6
7
8
📌 执行顺序:
@PostConstruct→InitializingBean→init-method
# 🔧 扩展点6:初始化后处理(AOP 在此!)
接口:BeanPostProcessor.postProcessAfterInitialization()
这是最重要的扩展点,Spring AOP 就是在这里生成代理对象的!
// AbstractAutoProxyCreator 的核心逻辑
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 检查是否需要代理(是否有 @Transactional、@Aspect 等)
return wrapIfNecessary(bean, beanName, cacheKey);
}
return bean;
}
2
3
4
5
6
7
8
9
🎯 关键结论:
@Transactional的代理是在 Bean 初始化完成后 才生成的- 因此在
@PostConstruct中调用同类事务方法,事务不生效(因为那时还是原始对象)
# 第二阶段:Bean 的销毁
当 Spring 容器关闭(如应用停止)时,会触发销毁流程:
// 销毁顺序(与初始化相反)
1. @PreDestroy 注解方法
2. DisposableBean.destroy()
3. 自定义 destroy-method
2
3
4
@Component
public class UserService implements DisposableBean {
@PreDestroy
public void preDestroy() {
System.out.println("@PreDestroy 执行");
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean 执行");
}
}
2
3
4
5
6
7
8
9
10
11
12
# 全流程总览图
Spring Bean 生命周期完整流程
═══════════════════════════════════════════════════════════════
【生成阶段】
1. 扫描类 → 生成 BeanDefinition(ASM 解析字节码)
2. 合并父子 BeanDefinition
3. 类加载(字符串 → Class<?>)
↓
🔧 扩展点:postProcessBeforeInstantiation() 【可替换对象】
↓
4. 实例化(new / 工厂方法 / Supplier)
↓
🔧 扩展点:postProcessMergedBeanDefinition() 【修改定义】
🔧 扩展点:postProcessAfterInstantiation() 【实例后处理】
↓
5. 自动注入(@Autowired / @Resource)
6. 属性填充
↓
🔧 扩展点:Aware 接口回调 【注入上下文】
↓
🔧 扩展点:postProcessBeforeInitialization() 【@PostConstruct 在此】
↓
7. 初始化(InitializingBean / init-method)
↓
🔧 扩展点:postProcessAfterInitialization() 【AOP 代理在此生成!】
↓
✅ Bean 就绪,投入使用
【销毁阶段】
1. @PreDestroy
2. DisposableBean.destroy()
3. destroy-method
═══════════════════════════════════════════════════════════════
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 常见面试题速查
# Q1:@Autowired 和 @Resource 的区别?
| 特性 | @Autowired | @Resource |
|---|---|---|
| 来源 | Spring 原生 | JSR-250 标准 |
| 默认匹配 | 先按类型,再按名称 | 先按名称,再按类型 |
| 指定方式 | @Qualifier | name 属性 |
| 处理类 | AutowiredAnnotationBeanPostProcessor | CommonAnnotationBeanPostProcessor |
# Q2:循环依赖是怎么解决的?
Spring 通过 三级缓存 解决 setter 注入的循环依赖:
- singletonObjects:成品 Bean(完全初始化)
- earlySingletonObjects:半成品 Bean(已实例化,未填充属性)
- singletonFactories:Bean 工厂(用于生成代理对象)
⚠️ 构造方法注入的循环依赖无法解决(因为实例化阶段就需要依赖)
# Q3:为什么 @Transactional 在 @PostConstruct 中不生效?
因为事务代理是在 postProcessAfterInitialization() 中生成的,而 @PostConstruct 在 postProcessBeforeInitialization() 中执行,此时还是原始对象,不是代理对象。
# 总结
理解 Spring 生命周期的关键是:知道扩展点在哪里,能解决什么问题。
| 你的需求 | 使用的扩展点 |
|---|---|
| 自定义依赖注入逻辑 | InstantiationAwareBeanPostProcessor.postProcessProperties() |
| 初始化前做点什么 | @PostConstruct 或 postProcessBeforeInitialization() |
| 生成 AOP 代理 | postProcessAfterInitialization() |
| 修改 BeanDefinition | MergedBeanDefinitionPostProcessor |
建议通读 AbstractAutowireCapableBeanFactory.doCreateBean() 源码,这是 Bean 生命周期的「主函数」。
本文基于 Spring 5.3.x 源码整理,如有错漏,欢迎指正。