容器是怎么管理 Bean 的?

文章目录

Spring 容器对 Bean 的管理不仅仅是"创建对象"那么简单,它实际上是一套极其严密的生命周期流水线

容器通过 BeanFactory (生产工厂)和 BeanDefinition(施工蓝图)这两个核心组件,完成了从读取配置到销毁对象的所有工作。


1. 核心蓝图:BeanDefinition

在容器真正 new 一个对象之前,它首先要把你的配置(XML、注解、Starter)转化成一个统一的内部结构:BeanDefinition

这个蓝图记录了:

  • Bean 的全类名(Class Name)。
  • 作用域(Scope):单例还是多例。
  • 是否懒加载(Lazy-init)。
  • 依赖关系:它需要注入哪些别的 Bean。
  • 初始化和销毁方法名。

2. 核心管理流程:生命周期流水线

你可以把容器想象成一个自动化工厂,每一个 Bean 都要走完以下流程:

第一阶段:准备与实例化

  1. 加载配置:容器启动,读取扫描路径下的所有类。
  2. 注册 BeanDefinition :将信息存入 BeanDefinitionMap
  3. 实例化(Instantiation):通过反射机制,调用构造函数创建一个"原生对象"。此时它只是个空的 Java 对象,还没注入数据。

第二阶段:装配与填充

  1. 属性赋值(Populate) :容器根据蓝图,把对应的配置参数和依赖的其他 Bean 注入进去(比如 @Value@Autowired)。
  2. Aware 回调 :如果 Bean 实现了 BeanNameAwareApplicationContextAware,容器会把 Bean 的名字或容器引用塞给它。

第三阶段:初始化(Initialization)

  1. BeanPostProcessor 前置处理 :执行所有拦截器的 postProcessBeforeInitialization 方法。
  2. 初始化方法 :先后执行 @PostConstructInitializingBean 接口方法、以及自定义的 init-method
  3. BeanPostProcessor 后置处理 :执行 postProcessAfterInitialization注意:AOP(动态代理)通常就在这一步发生。

第四阶段:生存与销毁

  1. 就绪:Bean 进入单例池(Singleton Objects Map),等待被业务代码调用。
  2. 销毁(Destruction) :当容器关闭时,执行销毁逻辑(@PreDestroy 等)。

3. 核心机制:三级缓存(解决循环依赖)

管理中最难的部分是:如果 A 依赖 B,B 也依赖 A 怎么办?

容器通过三级缓存(本质是三个 Map)来解决这个问题:

  • 一级缓存(singletonObjects):存放完全初始化好的、可以直接用的"成品"Bean。
  • 二级缓存(earlySingletonObjects):存放已经实例化、但还没填充属性的"半成品"Bean。
  • 三级缓存(singletonFactories):存放创建 Bean 的工厂对象,用来处理 AOP 情况下的循环依赖。

逻辑:A 创建时发现依赖 B,先把自己这个"半成品"挂在缓存里,跑去创建 B;B 发现依赖 A,直接从缓存里拿走 A 的"半成品"完成创建,再回头把完整的 B 给 A。


4. BeanFactory vs ApplicationContext

容器的管理能力也分等级:

特性 BeanFactory ApplicationContext
定位 底层接口,提供基本容器功能。 高级容器,继承了前者。
加载时机 懒加载。只有获取 Bean 时才创建。 预加载。容器启动时就创建所有单例。
扩展功能 无。 支持 AOP、国际化、事件广播、资源访问。
应用场景 移动端或资源极度受限环境(现已少用)。 几乎所有 Spring/Spring Boot 应用。

总结

容器管理 Bean 的本质是:利用 BeanDefinition 统一标准,利用"反射 + 缓存"实现自动化组装,利用"生命周期接口"提供可扩展性。

你现在已经看过了 Bean 的创建、销毁、以及容器的管理逻辑。你是否好奇过,为什么 Spring 默认要把 Bean 设计成单例(Singleton),这种设计在处理高并发请求时会有什么潜在的"坑"?

相关推荐
AI人工智能+电脑小能手1 小时前
【大白话说Java面试题】【Java基础篇】第40题:Java中的深拷贝和浅拷贝有什么区别
java·开发语言·后端·面试
@小匠1 小时前
云之家表单数据解析 skills (yzj-form-parser)
java
云烟成雨TD1 小时前
Spring AI Alibaba 1.x 系列【48】状态图编译配置类:CompileConfig 源码解析
java·人工智能·spring
贫民窟的勇敢爷们2 小时前
Java 与 Python 如何选型与融合
java·开发语言·python
小宇的天下3 小时前
Calibre DESIGNrev 单元(Cell)操作核心指南
java·前端·javascript
阿苟3 小时前
spring重点详解
java·后端·面试
Stream_Silver3 小时前
【JNA实战:Java无缝调用Windows API模拟键盘输入】
java·开发语言·windows
Sam_Deep_Thinking3 小时前
为什么选微服务而不是动态扩容单体
java·jvm·微服务
焦糖玛奇朵婷3 小时前
回收小程序开发案例分享
java·开发语言