Spring Bean 生命周期:初始化阶段高频面试题(含源码与实战案例)
一、核心初始化流程(必考)
完整生命周期链路
Bean 初始化是生命周期的核心环节,需结合前置的实例化、属性注入和后置的就绪阶段理解,完整流程如下:
graph TD
A[实例化 Bean] --> B[属性注入(@Autowired/setter)]
B --> C[Aware 接口回调(BeanNameAware 等)]
C --> D[BeanPostProcessor#postProcessBeforeInitialization]
D --> E[初始化核心逻辑]
E --> E1[@PostConstruct 注解方法]
E1 --> E2[InitializingBean#afterPropertiesSet]
E2 --> E3[自定义 init-method]
E --> F[BeanPostProcessor#postProcessAfterInitialization]
F --> G[Bean 就绪使用]
初始化阶段核心步骤解析(附源码佐证)
核心逻辑位于 AbstractAutowireCapableBeanFactory#initializeBean
方法,Spring 在此串联所有初始化步骤:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 1. Aware 接口回调(BeanNameAware/BeanFactoryAware 等)
invokeAwareMethods(beanName, bean);
// 2. BeanPostProcessor 前置处理
Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
// 3. 初始化核心逻辑(@PostConstruct/InitializingBean/init-method)
invokeInitMethods(beanName, wrappedBean, mbd);
// 4. BeanPostProcessor 后置处理(AOP 代理生成在此阶段)
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
return wrappedBean;
}
二、初始化核心组件对比(高频考点)
三大初始化方式深度对比
特性 | @PostConstruct | InitializingBean | init-method |
---|---|---|---|
规范来源 | JSR-250 标准注解 | Spring 内置接口 | Spring 配置驱动 |
触发时机 | 依赖注入完成后立即执行 | 依赖注入完成后,由 Spring 自动调用 | 需显式配置,最后执行 |
执行顺序 | 最早 | 次之 | 最晚 |
代码耦合性 | 低(非侵入式,仅注解) | 高(需实现 Spring 接口) | 低(配置与代码分离) |
适用场景 | 轻量级初始化(如属性校验) | 框架内部组件(如 Spring 源码) | 自定义复杂逻辑(如资源加载) |
代码案例:三种初始化方式的执行顺序验证
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.PostConstruct;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
// 1. 实现三种初始化方式的 Bean
class InitDemoBean implements InitializingBean {
// 方式1:@PostConstruct 注解方法
@PostConstruct
public void postConstructInit() {
System.out.println("1. @PostConstruct 执行");
}
// 方式2:InitializingBean 接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("2. InitializingBean.afterPropertiesSet 执行");
}
// 方式3:自定义 init-method 方法
public void customInitMethod() {
System.out.println("3. 自定义 init-method 执行");
}
}
// 2. 配置类(显式指定 init-method)
@Configuration
public class InitConfig