Bean的实例化过程
Spring Bean 实例化完整流程解析:从配置加载到 Bean 就绪
Spring Bean 的实例化是 IOC 容器的核心能力,并非简单的 “new 对象”,而是一套包含 “配置元信息解析→BeanDefinition 注册→容器增强→实例化→属性注入→初始化” 的完整链路。本文结合 BeanDefinitionReader、BeanDefinitionRegistry、BeanFactoryPostProcessor 等核心组件,从 “阶段拆解→组件作用→实战细节” 三个维度,彻底讲透 Bean 实例化的每一步。
Bean 实例化的整体链路(宏观视角)
Bean 实例化的本质是 “将配置元信息(XML / 注解)转化为可使用的 Bean 实例”,整体流程可分为 4 大阶段,每个阶段对应特定组件和职责:
graph TD
A[阶段1:配置元信息加载] --> B[阶段2:BeanDefinition生成与注册]
B --> C[阶段3:BeanFactoryPostProcessor增强]
C --> D[阶段4:Bean实例化与初始化]
D --> E["Bean就绪:可通过getBean()获取"]
每个阶段的核心目标:
- 阶段 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. 创建BeanFactory(DefaultListableBeanFactory是BeanDefinitionRegistry的实现)
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2. 创建XML读取器,关联BeanFactory
XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(beanFactory);
// 3. 加载XML配置文件(classpath下的spring-beans.xml)
xmlReader.loadBeanDefinitions(new ClassPathResource("spring-beans.xml"));
// 此时,XML中的<bean>已转化为BeanDefinition,注册到beanFactory中
对应的 spring-beans.xml 配置:
<beans>
<bean id="userService" class="com.example.UserService">
<property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" class="com.example.UserDao"/>
</beans>
(2)注解扫描加载(ClassPathBeanDefinitionScanner)
// 1. 创建BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2. 创建注解扫描器,指定扫描包
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(beanFactory);
// 3. 扫描com.example包下的@Component/@Service/@Repository/@Controller注解类
scanner.scan("com.example");
// 此时,注解类(如@Service UserService)已转化为BeanDefinition
(3)JavaConfig 加载(AnnotatedBeanDefinitionReader)
// 1. 创建BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2. 创建注解读取器
AnnotatedBeanDefinitionReader annotationReader = new AnnotatedBeanDefinitionReader(beanFactory);
// 3. 注册JavaConfig类(含@Bean注解)
annotationReader.register(AppConfig.class);
// AppConfig类:@Bean注解定义Bean
public class AppConfig {
public UserService userService() {
UserService service = new UserService();
service.setUserDao(userDao());
return service;
}
public UserDao userDao() {
return new UserDao();
}
}
阶段 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. 解析XML/注解生成BeanDefinition
BeanDefinition userServiceDefinition = BeanDefinitionBuilder
.genericBeanDefinition(UserService.class)
.addPropertyReference("userDao", "userDao") // 设置依赖:userDao引用
.setScope("singleton")
.getBeanDefinition();
// 2. 注册到BeanDefinitionRegistry(DefaultListableBeanFactory)
DefaultListableBeanFactory registry = new DefaultListableBeanFactory();
registry.registerBeanDefinition("userService", userServiceDefinition);
// 3. 查看注册结果(通过id获取BeanDefinition)
BeanDefinition registeredDef = registry.getBeanDefinition("userService");
System.out.println(registeredDef.getBeanClassName()); // 输出:com.example.UserService
阶段 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. 引入外部配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 2. BeanDefinition中使用占位符 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="url" value="${db.url}"/> <!-- ${db.url} 会被替换为配置文件中的值 -->
<property name="username" value="${db.username}"/>
</bean>
<!-- db.properties 内容 -->
db.url=jdbc:mysql://localhost:3306/test
db.username=root
(2)BeanDefinitionRegistryPostProcessor—— 注册新 BeanDefinition
BeanDefinitionRegistryPostProcessor 是 BeanFactoryPostProcessor 的子接口,扩展了 “注册新 BeanDefinition” 的能力,执行顺序先于普通 BeanFactoryPostProcessor。
示例(动态注册 BeanDefinition):
public class CustomBeanRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 动态创建UserService的BeanDefinition
BeanDefinition userServiceDef = BeanDefinitionBuilder
.genericBeanDefinition(UserService.class)
.addPropertyReference("userDao", "userDao")
.getBeanDefinition();
// 注册新BeanDefinition(id=dynamicUserService)
registry.registerBeanDefinition("dynamicUserService", userServiceDef);
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 可选:修改已注册的BeanDefinition(如修改userDao的属性)
BeanDefinition userDaoDef = beanFactory.getBeanDefinition("userDao");
userDaoDef.getPropertyValues().addPropertyValue("dbName", "test_db");
}
}
(3)执行顺序
多个 BeanFactoryPostProcessor 的执行顺序由接口控制:
PriorityOrdered接口:最高优先级,先执行;Ordered接口:中等优先级,次之;- 无接口:最低优先级,最后执行。
阶段 4:Bean 实例化与初始化 —— 从 “蓝图” 到 “可用 Bean”
经过前三个阶段,BeanDefinition 已准备就绪,Spring 开始基于 BeanDefinition 创建 Bean 实例,这是最核心的阶段,包含 “实例化→属性注入→初始化” 三步。
步骤 1:Bean 实例化 —— 创建对象(构造器 / 工厂)
Spring 根据 BeanDefinition 中的 “实例化策略” 创建 Bean 实例,支持 3 种方式:
(1)构造器实例化(默认)
- 无参构造器:默认策略,要求 Bean 类必须有无参构造器(若显式定义有参构造器,需手动添加无参构造器);
- 有参构造器:通过
constructor-arg配置参数,Spring 自动匹配构造器(按类型 / 索引 / 名称)。
示例(无参构造器实例化):
// BeanDefinition 信息
BeanDefinition userServiceDef = BeanDefinitionBuilder
.genericBeanDefinition(UserService.class) // 类名
.getBeanDefinition();
// Spring 内部实例化逻辑(简化)
Class<?> beanClass = Class.forName(userServiceDef.getBeanClassName());
Constructor<?> constructor = beanClass.getDeclaredConstructor(); // 获取无参构造器
Object beanInstance = constructor.newInstance(); // 实例化对象
(2)工厂方法实例化
- 静态工厂:
BeanDefinition中指定factoryClassName(静态工厂类)和factoryMethodName(静态方法); - 实例工厂:
BeanDefinition中指定factoryBeanName(实例工厂 Bean 的 id)和factoryMethodName(实例方法); - FactoryBean:实现
FactoryBean<T>接口,通过getObject()生成目标 Bean(你之前讨论过,需区分 “FactoryBean 本身” 和 “目标 Bean”)。
示例(FactoryBean 实例化):
// 1. 定义FactoryBean
public class UserFactoryBean implements FactoryBean<User> {
public User getObject() {
return new User("张三", 18); // 生成目标Bean
}
public Class<?> getObjectType() {
return User.class;
}
}
// 2. 注册FactoryBean的BeanDefinition
BeanDefinition factoryBeanDef = BeanDefinitionBuilder
.genericBeanDefinition(UserFactoryBean.class)
.getBeanDefinition();
registry.registerBeanDefinition("userFactoryBean", factoryBeanDef);
// 3. 获取目标Bean(Spring 自动调用getObject())
User user = beanFactory.getBean("userFactoryBean", User.class);
// 获取FactoryBean本身:加&前缀
UserFactoryBean factoryBean = beanFactory.getBean("&userFactoryBean", UserFactoryBean.class);
步骤 2:属性注入 —— 填充依赖
实例化对象后,Spring 通过 BeanWrapper 为对象注入属性(包括简单类型和引用类型),核心组件是 BeanWrapperImpl。
(1)属性注入的两种方式
- 手动注入:基于
BeanDefinition中的propertyValues(如 XML 的<property>、@Bean 中的setXxx); - 自动注入:基于
autowire属性(byName/byType/constructor),或注解@Autowired(由AutowiredAnnotationBeanPostProcessor处理)。
(2)核心逻辑(简化)
// 1. 创建BeanWrapper(包装实例化后的对象)
BeanWrapper beanWrapper = new BeanWrapperImpl(beanInstance);
// 2. 获取BeanDefinition中的属性值
PropertyValues pvs = userServiceDef.getPropertyValues(); // 含userDao的引用
// 3. 注入属性(处理引用类型:从BeanFactory获取依赖Bean)
beanWrapper.setPropertyValues(pvs);
// 此时,userServiceInstance的userDao属性已注入完成
(3)自动注入的关键:InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor 是 BeanPostProcessor 的子接口,在属性注入阶段发挥作用,例如:
AutowiredAnnotationBeanPostProcessor:处理@Autowired注解,扫描字段 / 方法并注入依赖;CommonAnnotationBeanPostProcessor:处理@Resource注解。
步骤 3:初始化 —— 增强 Bean(Aware→初始化方法→代理)
属性注入完成后,Spring 对 Bean 执行初始化逻辑,按以下顺序执行:
(1)Aware 接口回调
Bean 若实现 Aware 接口(如 BeanNameAware、BeanFactoryAware),Spring 会注入对应的容器服务:
// 示例:实现BeanNameAware
public class UserService implements BeanNameAware {
private String beanName;
public void setBeanName(String name) {
this.beanName = name; // Spring 注入当前Bean的id
}
}
(2)BeanPostProcessor 的 postProcessBeforeInitialization
所有 BeanPostProcessor 的前置处理方法,例如:
ApplicationContextAwareProcessor:处理ApplicationContextAware等接口;- 自定义
BeanPostProcessor:修改 Bean 实例(如添加日志增强)。
(3)初始化方法执行(按顺序)
- @PostConstruct:JSR-250 注解,Bean 构造后执行;
- InitializingBean:Spring 接口,执行
afterPropertiesSet()方法; - init-method:XML 或
@Bean(initMethod)指定的自定义初始化方法。
示例:
public class UserService implements InitializingBean {
public void postConstruct() {
System.out.println("1. @PostConstruct 执行");
}
public void afterPropertiesSet() throws Exception {
System.out.println("2. InitializingBean.afterPropertiesSet 执行");
}
// 对应 XML 的 init-method="init" 或 @Bean(initMethod = "init")
public void init() {
System.out.println("3. 自定义 init-method 执行");
}
}
(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 直接返回