目录
- 概览
- 生命周期总览(含流程图)
- 核心接口与机制
- 实战示例(代码)
- 可利用生命周期实现的场景
- 源码层级简析(关键方法)
- 常见坑与建议
- 总结
概览
在 Spring 容器中,Bean 从创建到销毁会经历一系列阶段:定义解析 → 实例化 → 依赖注入 → 回调与初始化 → 可用 → 销毁。这些阶段是容器管理对象、插入钩子(例如 AOP、事件、初始化任务)以及实现自动化的一套机制的基础。
生命周期总览(含流程图)
1 BeanDefinition 解析 2 实例化 Instantiation 3 属性填充 Dependency Injection 4 Aware 接口回调 5 BeanPostProcessor 前置处理 6 初始化 init-method 或 InitializingBean 7 BeanPostProcessor 后置处理 8 Bean 可用 使用阶段 9 容器关闭时销毁 Destroy
阶段要点(简略):
- BeanDefinition 解析:从注解或 XML/JavaConfig 读取元数据。
- 实例化:通过反射或构造器创建对象。
- 属性填充:完成依赖注入(构造注入 / 设值注入)。
- Aware 回调:如
BeanNameAware、ApplicationContextAware获取容器上下文。 - BeanPostProcessor:在初始化前后对 Bean 做增强(常用于创建代理)。
- 初始化:
@PostConstruct/InitializingBean#afterPropertiesSet()/ 自定义init-method。 - 销毁:
@PreDestroy/DisposableBean#destroy()在容器关闭时执行清理。
核心接口与机制
| 接口 / 注解 | 阶段 | 作用 |
|---|---|---|
BeanNameAware |
Aware | 获取 Bean 名称 |
BeanFactoryAware |
Aware | 获取 BeanFactory 引用 |
ApplicationContextAware |
Aware | 获取 ApplicationContext |
InitializingBean / @PostConstruct |
初始化 | 属性注入后执行初始化逻辑 |
DisposableBean / @PreDestroy |
销毁 | 容器关闭前释放资源 |
BeanPostProcessor |
前后置处理 | 创建代理、注入增强逻辑 |
BeanFactoryPostProcessor |
容器启动早期 | 修改 BeanDefinition 或动态注册 Bean |
实战示例(代码)
1) 使用 @PostConstruct 与 @PreDestroy
@Component
public class CacheService {
@PostConstruct
public void initCache() {
// 启动时预热缓存
System.out.println("初始化缓存");
// loadCache();
}
@PreDestroy
public void shutdown() {
// 关闭时释放资源
System.out.println("清理缓存资源");
// closeConnections();
}
}
2) 使用 BeanPostProcessor 做简单增强(示例)
@Component
public class LoggingBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 在初始化前记录
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// 在初始化后可以返回代理
if (bean instanceof MyService) {
// return ProxyFactory.getProxy(bean);
}
return bean;
}
}
3) 使用 SmartLifecycle 控制启动顺序(长生命周期组件)
@Component
public class MyServiceLifecycle implements SmartLifecycle {
private boolean running = false;
@Override
public void start() {
// 在上下文刷新后按顺序启动
running = true;
}
@Override
public void stop() {
running = false;
}
@Override
public boolean isRunning() {
return running;
}
@Override
public int getPhase() {
// phase 决定启动与停止顺序,值越小越先启动
return 0;
}
}
可利用生命周期实现的场景
- 配置加载与验证:在初始化阶段加载并校验外部配置(数据库、第三方服务)。
- 缓存预热 / 线程池创建:在启动时初始化必须的资源,避免首次请求阻塞。
- 自动注册:应用启动时自动向注册中心或配置中心注册自身信息。
- 运行时增强 :通过
BeanPostProcessor在 Bean 初始化后替换为代理以实现 AOP、权限或度量统计。 - 优雅关闭 :在
@PreDestroy或DisposableBean中释放连接、持久化内存状态、发送下线事件。
源码层级简析(关键方法)
Spring 的 Bean 创建核心在 AbstractAutowireCapableBeanFactory,伪代码流程如下:
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) {
// 1. 实例化
Object bean = createBeanInstance(beanName, mbd, args);
// 2. 属性注入
populateBean(beanName, mbd, instanceWrapper);
// 3. before init
bean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
// 4. init
invokeInitMethods(beanName, bean, mbd);
// 5. after init
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
return bean;
}
理解此流程有助于在合适的环节注入自定义逻辑(如动态代理、自动化校验、注册等)。
常见坑与建议
| 场景 | 问题 | 建议 |
|---|---|---|
| 注解不生效 | @PostConstruct / @PreDestroy 不触发 |
确保类被 Spring 管理(如 @Component ) |
| 循环依赖 | 构造器注入导致循环 | 尽量使用构造器注入保证不可变,或对部分依赖使用 @Lazy |
| 初始化耗时 | 阻塞启动 | 将耗时任务异步化或延迟执行,避免阻塞容器启动 |
| 资源未释放 | @PreDestroy 不触发 |
使用 ApplicationContext 正常关闭(context.close()),避免强制退出 JVM |
| 滥用 BeanPostProcessor | 性能下降 | 限定处理对象类型,避免每个 Bean 都做大量反射/代理 |
总结
Spring Bean 生命周期是理解整个 Spring IoC 容器运行机制的核心 :
从 BeanDefinition 解析 → 实例化 → 依赖注入 → 初始化 → 使用 → 销毁 ,每一步都为容器提供了精确的可插拔扩展点,保证了框架的灵活性与可扩展性。
在工程实践中,合理利用生命周期机制,可以实现:
- 缓存预热:在应用启动阶段提前加载热点数据,提升首屏性能;
- 自动注册 / 自动上报:在初始化阶段自动向注册中心、配置中心或监控系统上报实例;
- 代理增强与拦截 :通过
BeanPostProcessor动态创建代理,实现 AOP、日志、安全控制; - 资源回收与优雅关闭:在销毁阶段释放连接、保存状态,保障系统平滑停机;
- 启动验证与健康检测:在容器完成加载后执行自检逻辑,确保依赖和外部服务可用。