Spring Bean 实例化完整流程解析:从配置加载到 Bean 就绪
Spring Bean 的实例化是 IOC 容器的核心能力,并非简单的 “new 对象”,而是一套包含 “配置元信息解析→BeanDefinition 注册→容器增强→实例化→属性注入→初始化” 的完整链路。本文结合 BeanDefinitionReader
、BeanDefinitionRegistry
、BeanFactoryPostProcessor
等核心组件,从 “阶段拆解→组件作用→实战细节” 三个维度,彻底讲透 Bean 实例化的每一步。
Bean 实例化的整体链路(宏观视角)
Bean 实例化的本质是 “将配置元信息(XML / 注解)转化为可使用的 Bean 实例”,整体流程可分为 4 大阶段,每个阶段对应特定组件和职责:
每个阶段的核心目标:
- 阶段 1:读取外部配置(XML / 注解 / JavaConfig),转化为 Spring 可识别的 “元信息”;
- 阶段 2:将元信息封装为
BeanDefinition
(Bean 的 “蓝图”),并注册到容器; - 阶段 3:修改 / 增强
BeanDefinition
(如替换占位符、动态注册新 Bean); - 阶段 4:基于
BeanDefinition
创建实例、注入属性、执行初始化,最终生成可用 Bean。
阶段 1:配置元信息加载 —— 告诉 Spring “要创建哪些 Bean”
Spring 无法主动感知需要创建的 Bean,必须通过配置元信息明确告知。配置方式分为 “XML 配置”“注解配置”“JavaConfig 配置”,对应不同的 BeanDefinitionReader
来加载。
1. 核心组件:BeanDefinitionReader(元信息读取器)
BeanDefinitionReader
是加载配置元信息的顶层接口,不同配置方式对应不同实现类:
实现类 | 适用配置方式 | 核心作用 |
---|---|---|
XmlBeanDefinitionReader |
XML 配置(如 applicationContext.xml) | 解析 XML 中的 <bean> 标签,生成 BeanDefinition |
AnnotatedBeanDefinitionReader |
显式注解配置(如 @Bean、@Component) | 解析类 / 方法上的注解,生成 BeanDefinition |
ClassPathBeanDefinitionScanner |
注解扫描(如 @ComponentScan) | 扫描指定包下的注解类(@Component/@Service 等),生成 BeanDefinition |
2. 不同配置方式的加载示例
(1)XML 配置加载(XmlBeanDefinitionReader)
1 | // 1. 创建BeanFactory(DefaultListableBeanFactory是BeanDefinitionRegistry的实现) |
对应的 spring-beans.xml
配置:
1 | <beans> |
(2)注解扫描加载(ClassPathBeanDefinitionScanner)
1 | // 1. 创建BeanFactory |
(3)JavaConfig 加载(AnnotatedBeanDefinitionReader)
1 | // 1. 创建BeanFactory |
阶段 2:BeanDefinition 生成与注册 —— 创建 Bean 的 “蓝图”
配置元信息加载后,Spring 会将其封装为 BeanDefinition
(Bean 的定义信息),并注册到 BeanDefinitionRegistry
(BeanDefinition 的 “仓库”)。
1. 核心组件 1:BeanDefinition(Bean 的 “蓝图”)
BeanDefinition
是 Bean 的元数据容器,包含创建 Bean 所需的所有信息,相当于 “创建 Bean 的说明书”,核心属性如下:
属性 | 作用 | 示例值 |
---|---|---|
beanClassName |
Bean 对应的全类名 | “com.example.UserService” |
scope |
Bean 作用域(singleton/prototype 等) | “singleton” |
propertyValues |
Bean 的属性值(含依赖引用) | 存储 userDao 的引用(ref=”userDao”) |
initMethodName |
初始化方法名 | “init”(对应 XML 的 init-method) |
destroyMethodName |
销毁方法名 | “destroy”(对应 XML 的 destroy-method) |
abstract |
是否为抽象 Bean(不可实例化) | false |
factoryBeanName |
工厂 Bean 名称(工厂方法实例化时用) | “userFactory”(实例工厂 Bean 的 id) |
factoryMethodName |
工厂方法名(静态 / 实例工厂) | “createUserService” |
2. 核心组件 2:BeanDefinitionRegistry(BeanDefinition 仓库)
BeanDefinitionRegistry
是注册 BeanDefinition
的接口,核心实现类是 DefaultListableBeanFactory
(大多数容器的底层实现),其内部通过 Map<String, BeanDefinition>
存储 “Bean id → BeanDefinition” 的映射。
注册过程示例(Spring 内部逻辑简化):
1 | // 1. 解析XML/注解生成BeanDefinition |
阶段 3:BeanFactoryPostProcessor 增强 —— 修改 Bean 的 “蓝图”
在 Bean 实例化之前,Spring 会调用 BeanFactoryPostProcessor
对 BeanDefinition
进行修改或增强,这是 Spring 扩展容器的关键扩展点( PropertySourcesPlaceholderConfigurer
就是典型实现)。
1. BeanFactoryPostProcessor 的核心作用
- 修改已注册的 BeanDefinition:如替换属性中的
${}
占位符、修改作用域、添加属性; - 不创建 Bean 实例:仅操作
BeanDefinition
(元数据),此时 Bean 尚未实例化; - 执行时机:所有
BeanDefinition
注册完成后,Bean 实例化前。
2. 关键实现类解析
(1)PropertySourcesPlaceholderConfigurer—— 替换占位符
PropertySourcesPlaceholderConfigurer
是最常用的实现类,核心功能是替换 BeanDefinition
中 ${key}
形式的占位符(如 ${db.url}
)。
工作流程:
- 加载外部配置文件(如
application.properties
); - 遍历所有
BeanDefinition
的propertyValues
; - 将
${key}
替换为配置文件中的对应值; - 更新
BeanDefinition
的属性值。
示例(XML 配置):
1 | <!-- 1. 引入外部配置文件 --> |
(2)BeanDefinitionRegistryPostProcessor—— 注册新 BeanDefinition
BeanDefinitionRegistryPostProcessor
是 BeanFactoryPostProcessor
的子接口,扩展了 “注册新 BeanDefinition
” 的能力,执行顺序先于普通 BeanFactoryPostProcessor
。
示例(动态注册 BeanDefinition):
1 |
|
(3)执行顺序
多个 BeanFactoryPostProcessor
的执行顺序由接口控制:
PriorityOrdered
接口:最高优先级,先执行;Ordered
接口:中等优先级,次之;- 无接口:最低优先级,最后执行。
阶段 4:Bean 实例化与初始化 —— 从 “蓝图” 到 “可用 Bean”
经过前三个阶段,BeanDefinition
已准备就绪,Spring 开始基于 BeanDefinition
创建 Bean 实例,这是最核心的阶段,包含 “实例化→属性注入→初始化” 三步。
步骤 1:Bean 实例化 —— 创建对象(构造器 / 工厂)
Spring 根据 BeanDefinition
中的 “实例化策略” 创建 Bean 实例,支持 3 种方式:
(1)构造器实例化(默认)
- 无参构造器:默认策略,要求 Bean 类必须有无参构造器(若显式定义有参构造器,需手动添加无参构造器);
- 有参构造器:通过
constructor-arg
配置参数,Spring 自动匹配构造器(按类型 / 索引 / 名称)。
示例(无参构造器实例化):
1 | // BeanDefinition 信息 |
(2)工厂方法实例化
- 静态工厂:
BeanDefinition
中指定factoryClassName
(静态工厂类)和factoryMethodName
(静态方法); - 实例工厂:
BeanDefinition
中指定factoryBeanName
(实例工厂 Bean 的 id)和factoryMethodName
(实例方法); - FactoryBean:实现
FactoryBean<T>
接口,通过getObject()
生成目标 Bean(你之前讨论过,需区分 “FactoryBean 本身” 和 “目标 Bean”)。
示例(FactoryBean 实例化):
1 | // 1. 定义FactoryBean |
步骤 2:属性注入 —— 填充依赖
实例化对象后,Spring 通过 BeanWrapper
为对象注入属性(包括简单类型和引用类型),核心组件是 BeanWrapperImpl
。
(1)属性注入的两种方式
- 手动注入:基于
BeanDefinition
中的propertyValues
(如 XML 的<property>
、@Bean 中的setXxx
); - 自动注入:基于
autowire
属性(byName/byType/constructor),或注解@Autowired
(由AutowiredAnnotationBeanPostProcessor
处理)。
(2)核心逻辑(简化)
1 | // 1. 创建BeanWrapper(包装实例化后的对象) |
(3)自动注入的关键:InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor
是 BeanPostProcessor
的子接口,在属性注入阶段发挥作用,例如:
AutowiredAnnotationBeanPostProcessor
:处理@Autowired
注解,扫描字段 / 方法并注入依赖;CommonAnnotationBeanPostProcessor
:处理@Resource
注解。
步骤 3:初始化 —— 增强 Bean(Aware→初始化方法→代理)
属性注入完成后,Spring 对 Bean 执行初始化逻辑,按以下顺序执行:
(1)Aware 接口回调
Bean 若实现 Aware
接口(如 BeanNameAware
、BeanFactoryAware
),Spring 会注入对应的容器服务:
1 | // 示例:实现BeanNameAware |
(2)BeanPostProcessor 的 postProcessBeforeInitialization
所有 BeanPostProcessor
的前置处理方法,例如:
ApplicationContextAwareProcessor
:处理ApplicationContextAware
等接口;- 自定义
BeanPostProcessor
:修改 Bean 实例(如添加日志增强)。
(3)初始化方法执行(按顺序)
- @PostConstruct:JSR-250 注解,Bean 构造后执行;
- InitializingBean:Spring 接口,执行
afterPropertiesSet()
方法; - init-method:XML 或
@Bean(initMethod)
指定的自定义初始化方法。
示例:
1 | public class UserService implements InitializingBean { |
(4)BeanPostProcessor 的 postProcessAfterInitialization
所有 BeanPostProcessor
的后置处理方法,AOP 代理生成的关键阶段:
- Spring AOP 的
AnnotationAwareAspectJAutoProxyCreator
在此阶段为 Bean 生成代理对象(若匹配切面)。
步骤 4:Bean 就绪 —— 加入容器缓存
- 单例 Bean:实例化完成后,存入
DefaultListableBeanFactory
的singletonObjects
缓存(键:Bean id,值:Bean 实例),后续getBean()
直接从缓存获取; - 原型 Bean:不存入缓存,每次
getBean()
都会重新执行 “实例化→属性注入→初始化” 流程。
关键细节与注意事项
- 单例 vs 原型的实例化时机:
- 单例 Bean:默认在容器启动时实例化(可通过
@Lazy
延迟到首次getBean()
); - 原型 Bean:仅在调用
getBean()
时实例化。
- 单例 Bean:默认在容器启动时实例化(可通过
- 循环依赖的解决:
- Spring 通过 “三级缓存” 解决单例 Bean 的循环依赖(
singletonFactories
→earlySingletonObjects
→singletonObjects
); - 原型 Bean 的循环依赖无法解决,会抛出
BeanCurrentlyInCreationException
。
- Spring 通过 “三级缓存” 解决单例 Bean 的循环依赖(
- FactoryBean 的特殊处理:
- 调用
getBean("factoryBeanId")
时,返回FactoryBean.getObject()
的结果; - 调用
getBean("&factoryBeanId")
时,返回FactoryBean
本身。
- 调用
总结:Bean 实例化全流程(精简版)
- 配置加载:
BeanDefinitionReader
读取 XML / 注解,生成BeanDefinition
; - 注册蓝图:
BeanDefinition
注册到BeanDefinitionRegistry
; - 增强蓝图:
BeanFactoryPostProcessor
修改BeanDefinition
(如替换占位符); - 实例化:通过构造器 / 工厂方法创建 Bean 实例;
- 属性注入:
BeanWrapper
注入属性,InstantiationAwareBeanPostProcessor
处理自动注入; - 初始化:Aware 回调→
postProcessBeforeInitialization
→初始化方法→postProcessAfterInitialization
(AOP 代理); - 就绪:单例 Bean 存入缓存,原型 Bean 直接返回
v1.3.10