一个 Bean 的诞生
getBean("orderService") 一行调用,背后是一条九步流水线。先看全景,再逐站拆解:
1 解析类定义 → 2 实例化(构造器)→ 3 属性填充(@Autowired)
→ 4 Aware 回调(BeanNameAware / ApplicationContextAware ...)
→ 5 BeanPostProcessor#postProcessBeforeInitialization
→ 6 初始化(@PostConstruct → InitializingBean → init-method)
→ 7 BeanPostProcessor#postProcessAfterInitialization(AOP 代理在这诞生)
→ 8 使用中 → 9 销毁(@PreDestroy → DisposableBean → destroy-method)记忆分组:1-3 造出来(解析、实例化、装配),4-7 增强与初始化(回调、两道后置处理器关卡),9 收尾(三层销毁)。
初始化三道工序:注解 → 接口 → 配置
第 6 步里有三道固定顺序的工序:@PostConstruct 先跑(CommonAnnotationBeanPostProcessor 干的)、然后 InitializingBean 的 afterPropertiesSet(Spring 接口级)、最后 init-method 声明的自定义方法(配置级)。从「最贴近业务」到「最贴近容器」。销毁完全对称反着来:@PreDestroy → DisposableBean → destroy-method。
BeanPostProcessor:两道关卡
生命周期里最重要的角色是 BeanPostProcessor——它在初始化前后各设一关,每个 Bean 都要过。@Autowired 的注入靠 AutowiredAnnotationBeanPostProcessor 在属性填充阶段解析;@PostConstruct 靠 CommonAnnotationBeanPostProcessor 识别;AOP 代理在 postProcessAfterInitialization 里生成(AbstractAutoProxyCreator)。可以说 Spring 的「魔法」九成九是后置处理器干的——第 4 篇专门拆它。
单例池:终点站
初始化完成的单例 Bean 进入 singletonObjects 单例池,之后 getBean 直接命中返回——这就是 Bean 默认单例的原因,也是「无状态才安全」的原因:单例对象被所有请求共享,放个可变成员变量就是并发事故。至于「A 依赖 B、B 依赖 A」的循环依赖怎么在创建途中解决——单例池只是答案的三分之一,完整答案藏在三级缓存里,第 3 篇专讲。
实操:亲眼看一遍
@Component
public class LifecycleBean implements InitializingBean, DisposableBean {
public LifecycleBean() {
System.out.println("2 实例化");
}
@Autowired
public void setDependency(Dependency d) {
System.out.println("3 属性填充");
}
@PostConstruct
public void postConstruct() {
System.out.println("6-1 @PostConstruct");
}
@Override
public void afterPropertiesSet() {
System.out.println("6-2 afterPropertiesSet");
}
@PreDestroy
public void preDestroy() {
System.out.println("9-1 @PreDestroy");
}
@Override
public void destroy() {
System.out.println("9-2 destroy");
}
}启动再关闭,控制台输出顺序就是生命周期。面试被问「Bean 生命周期」,能按顺序讲出每一步「谁干的」(哪个后置处理器、哪个接口回调),就赢过九成背八股的。
地基铺好,下一篇拆 Spring 最精巧的设计之一:三级缓存与循环依赖——为什么是三级而不是两级,为什么实例化刚完成就要提前曝光。
评论 (0)