Spring Bean 生命周期
一、图解生命周期 4 大阶段

【Spring Bean 生命周期 - 4 大阶段】
阶段 1:Bean 定义(BeanDefinition)
↓
阶段 2:实例化(构造方法 / 工厂方法)
↓
阶段 3:初始化赋值(依赖注入 → Aware 接口 → BeanPostProcessor → 初始化方法)
↓
阶段 4:销毁 bean
Bean 的创建和初始化赋值是分开的"——这是核心,**很多老开发都搞混"实例化"和"初始化"。
二、阶段 1:Bean 定义(BeanDefinition)
2.1 触发时机
Spring 启动时(不是 @Autowired 时!),Spring 扫描所有 @Component / @Service / @Controller / @Repository / @Bean,为每个类生成一个 BeanDefinition。
2.2 BeanDefinition 包含什么
public class BeanDefinition { private String beanClassName; // 类全限定名 private String factoryBeanName; // 工厂 Bean 名(@Configuration 用) private String factoryMethodName; // 工厂方法名 private String scope; // singleton / prototype private boolean lazyInit; // 是否懒加载 private String initMethodName; // 初始化方法 private String destroyMethodName; // 销毁方法 private ConstructorArgumentValues constructorArgumentValues; // 构造参数 private MutablePropertyValues propertyValues; // 属性值 // ... 还有很多}
2.3 项目对应
@Service // ✅ Spring 启动时扫描到这个注解,生成 BeanDefinition
public class PerformanceService {
// ...
}
三、阶段 2:实例化(Instantiation)
3.1 触发时机
第一次 getBean() 时(singleton 在容器启动时实例化,prototype 在 getBean 时实例化)。
3.2 实例化做了什么
调用构造方法创建对象(但还没赋值!):
@Service
public class UserService {
@Autowired // ⚠️ 此时还没注入!
private UserDao userDao;
public UserService() { // ✅ 构造方法被调用
System.out.println("实例化:userDao = " + userDao); // null
}
}
输出:
实例化:userDao = null // ⚠️ 此时 userDao 还是 null
3.3 4 种实例化方式
方式 例子
默认构造方法 new UserService()
有参构造方法 new UserService("name", 18)
静态工厂方法 UserService.create()
实例工厂方法 factoryBean.createUserService()
Spring 选择顺序: @Autowired 构造方法 > 默认构造方法 > 静态工厂 > 实例工厂
3.4 项目对应
@Component
public class BusinessConsumer {
@Autowired
private StringRedisTemplate redisTemplate; // 阶段 3 才注入
public BusinessConsumer() {
// 阶段 2:实例化(redisTemplate 还是 null)
}
}
四、阶段 3:初始化赋值(核心阶段)
4.1 5个小步骤(按顺序!)
- 依赖注入(@Autowired / @Resource / @Value)
↓ - Aware 接口回调(BeanNameAware / BeanFactoryAware / ApplicationContextAware)
↓ - BeanPostProcessor#before(前置处理)
↓ - 初始化方法(@PostConstruct / InitializingBean / 自定义 init-method)
↓ - BeanPostProcessor#after(后置处理,AOP 代理在这里生成!)
4.2 步骤 1:依赖注入
@Service
public class UserService {
@Autowired
private UserDao userDao; // ✅ 步骤 1:此时注入
public UserService() {
System.out.println(userDao); // null(步骤 2 才注入)
}
}
关键事实:
构造方法执行时,userDao 是 null(实例化阶段)
依赖注入发生在实例化之后、初始化之前
4.3 步骤 2:Aware 接口回调
@Service
public class UserService implements BeanNameAware, BeanFactoryAware, ApplicationContextAware {
@Override
public void setBeanName(String name) { // BeanNameAware
System.out.println("Bean 名字:" + name);
}
@Override
public void setBeanFactory(BeanFactory factory) { // BeanFactoryAware
System.out.println("BeanFactory 注入");
}
@Override
public void setApplicationContext(ApplicationContext ctx) { // ApplicationContextAware
System.out.println("ApplicationContext 注入");
}
}
3 个常见 Aware 接口:
接口 注入什么 项目实战
BeanNameAware Bean 的名字 一般不用
BeanFactoryAware BeanFactory 获取其他 Bean
ApplicationContextAware ApplicationContext 项目里用过(拿 Spring 容器)
4.4 步骤 3:BeanPostProcessor#before(Spring 扩展点)
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("Before: " + beanName);
return bean; // 可以返回包装后的 bean
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("After: " + beanName);
return bean;
}
}
这个接口的 3 大作用:
✅ AOP 代理生成(@EnableAspectJAutoProxy 内部用这个)
✅ 自定义注解处理
✅ Bean 包装(返回代理对象)
4.5 步骤 4:初始化方法(3 种方式)
@Service
public class UserService {
// 方式 1:@PostConstruct(JSR-250 注解)
@PostConstruct
public void init() {
System.out.println("@PostConstruct 初始化");
}
// 方式 2:InitializingBean 接口
public class UserService implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean 初始化");
}
}
// 方式 3:自定义 init-method(XML 配置)
//
public void customInit() {
System.out.println("自定义 init-method 初始化");
}
}
执行顺序(3 种方式):
- @PostConstruct
- InitializingBean#afterPropertiesSet
- 自定义 init-method
4.6 步骤 5:BeanPostProcessor#after(AOP 代理生成!)
// AbstractAutowireCapableBeanFactory.doCreateBean()
protected Object initializeBean(...) {
// 1. 依赖注入
// 2. Aware 回调
// 3. BeanPostProcessor#before
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
// 4. 初始化方法(@PostConstruct / InitializingBean)
invokeInitMethods(beanName, wrappedBean, mbd);
// 5. BeanPostProcessor#after(AOP 代理生成!)
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
}
关键事实:AOP 代理在 BeanPostProcessor#after 阶段生成(所以 @Transactional 方法被调用时才有事务)。
4.7 项目对应
报表生成 Service:
@Service
public class ReportGeneratorService implements InitializingBean {
@Autowired // 步骤 1:依赖注入
private DataSource dataSource;
@Autowired
private ReportTemplateLoader templateLoader;
@Override // 步骤 2.3:InitializingBean 初始化
public void afterPropertiesSet() throws Exception {
// 报表模板预加载
templateLoader.preload();
}
@Transactional // 步骤 5:AOP 代理在这里加事务拦截
public void generateReport(ReportQuery query) {
// ...
}
}
五、阶段 4:销毁 bean
5.1 触发时机
容器关闭时(ctx.close())
Web 应用停止时
Spring Boot shutdown hook
5.2 3 种销毁方式
@Service
public class UserService {
// 方式 1:@PreDestroy
@PreDestroy
public void cleanup() {
System.out.println("@PreDestroy 销毁");
}
// 方式 2:DisposableBean 接口
public class UserService implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean 销毁");
}
}
// 方式 3:自定义 destroy-method
public void customDestroy() {
System.out.println("自定义 destroy-method 销毁");
}
}
执行顺序: @PreDestroy → DisposableBean#destroy → 自定义 destroy-method
5.3 关键事实:prototype Bean 不会触发销毁
@Service
@Scope("prototype")
public class ShoppingCart { // ⚠️ prototype 的销毁 Spring 不管
@PreDestroy
public void cleanup() { ... } // 不会触发
}
销毁逻辑必须自己写。
六、完整生命周期时序图
[Spring 启动]
↓
[1] 扫描 @Component/@Service/@Controller/@Repository/@Bean
↓ 生成 BeanDefinition
[2] 实例化(new UserService())
↓ 构造方法执行
[3] 依赖注入(@Autowired / @Resource / @Value)
↓ 成员变量赋值
[4] Aware 接口回调
↓ BeanNameAware / BeanFactoryAware / ApplicationContextAware
[5] BeanPostProcessor#before
↓ 前置处理
[6] 初始化方法
↓ @PostConstruct → InitializingBean → init-method
[7] BeanPostProcessor#after
↓ AOP 代理生成(@Transactional / @Async / 自定义 AOP)
[8] Bean 放入容器(singleton 缓存)
↓
[9] 业务使用期
↓
[10] 容器关闭
↓
[11] 销毁方法
↓ @PreDestroy → DisposableBean → destroy-method
七、面试官追问应对
追问:Spring Bean 生命周期有哪些阶段?
"4 大阶段:
1.Bean 定义(生成 BeanDefinition)
2.实例化(new 对象,不赋值)
3.初始化赋值(依赖注入 → Aware → BeanPostProcessor → 初始化方法)
4.销毁 bean(@PreDestroy → DisposableBean → destroy-method)
关键:AOP 代理在 BeanPostProcessor#after 阶段生成,所以 @Transactional 方法被调用时才有事务。"
追问 2:构造方法和 @PostConstruct 谁先执行?
"构造方法先执行(实例化阶段),@PostConstruct 后执行(初始化阶段)。
所以构造方法里调用成员变量是 null(依赖还没注入),@PostConstruct 里调用成员变量是有值的(依赖已注入)。
老哥 DLQ Demo 里,构造方法执行时 redisTemplate 还是 null,@PostConstruct 里 redisTemplate 才有值。"
追问 3:@PostConstruct 和 InitializingBean 哪个先?
"@PostConstruct 先(JSR-250 标准注解,Spring 推荐)。
执行顺序:
1.@PostConstruct
2.InitializingBean#afterPropertiesSet
3.自定义 init-method
老哥项目里推荐用 @PostConstruct(标准化、跨框架)。"
追问 4:AOP 代理什么时候生成?
"BeanPostProcessor#after 阶段生成。
这就是为什么 @Transactional / @Async / 自定义 AOP 必须在 Spring 容器管理的 Bean 上才生效,因为代理是在初始化阶段生成的。
如果用 new UserService() 创建对象,没有代理,事务不生效。"
追问 5:循环依赖怎么解决?
"3 级缓存:
1.singletonObjects:完整 Bean(一级缓存)
2.earlySingletonObjects:早期引用(二级缓存)
3.singletonFactories:ObjectFactory(三级缓存)
解决流程:
A 创建 → 暴露 ObjectFactory → 属性注入(发现依赖 B)
B 创建 → 暴露 ObjectFactory → 属性注入(发现依赖 A)
A 从三级缓存获取早期引用 → B 注入成功 → B 创建完成
A 注入 B → A 创建完成
注意:构造方法注入的循环依赖无法解决(因为构造时还没暴露早期引用),必须用 @Autowired 字段注入或 setter 注入。"
追问 6:prototype Bean 的循环依赖能解决吗?
"不能。prototype 不放入三级缓存,所以循环依赖会抛 BeanCurrentlyInCreationException。
解决:用 @Lazy(延迟加载)。"
八、记忆口诀
"4大阶段:定义 → 实例化 → 初始化 → 销毁"
"实例化不赋值,初始化才赋值"
"@PostConstruct 先于 InitializingBean"
"AOP 代理在 BeanPostProcessor#after 阶段生成"
"构造方法依赖是 null,@PostConstruct 依赖是有值的"
"3级缓存解决循环依赖,构造注入无解
prototype Bean,销毁逻辑必须自己写"

浙公网安备 33010602011771号