一、图解生命周期 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 配置)
// <bean id="userService" class="..." init-method="customInit"/>
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 里调用成员变量是有值的(依赖已注入)。
构造方法执行时 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 级缓存解决循环依赖,构造注入无解"