0%

Bean的实例化过程

Spring Bean 实例化完整流程解析:从配置加载到 Bean 就绪

Spring Bean 的实例化是 IOC 容器的核心能力,并非简单的 “new 对象”,而是一套包含 “配置元信息解析→BeanDefinition 注册→容器增强→实例化→属性注入→初始化” 的完整链路。本文结合 BeanDefinitionReaderBeanDefinitionRegistryBeanFactoryPostProcessor 等核心组件,从 “阶段拆解→组件作用→实战细节” 三个维度,彻底讲透 Bean 实例化的每一步。

Bean 实例化的整体链路(宏观视角)

Bean 实例化的本质是 “将配置元信息(XML / 注解)转化为可使用的 Bean 实例”,整体流程可分为 4 大阶段,每个阶段对应特定组件和职责:

阶段1:配置元信息加载
阶段2:BeanDefinition生成与注册
阶段3:BeanFactoryPostProcessor增强
阶段4:Bean实例化与初始化
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
2
3
4
5
6
7
8
9
10
// 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 配置:

1
2
3
4
5
6
<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
2
3
4
5
6
7
8
9
10
// 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 1. 创建BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

// 2. 创建注解读取器
AnnotatedBeanDefinitionReader annotationReader = new AnnotatedBeanDefinitionReader(beanFactory);

// 3. 注册JavaConfig类(含@Bean注解)
annotationReader.register(AppConfig.class);

// AppConfig类:@Bean注解定义Bean
@Configuration
public class AppConfig {
@Bean
public UserService userService() {
UserService service = new UserService();
service.setUserDao(userDao());
return service;
}

@Bean
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
2
3
4
5
6
7
8
9
10
11
12
13
14
// 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 会调用 BeanFactoryPostProcessorBeanDefinition 进行修改或增强,这是 Spring 扩展容器的关键扩展点( PropertySourcesPlaceholderConfigurer 就是典型实现)。

1. BeanFactoryPostProcessor 的核心作用

  • 修改已注册的 BeanDefinition:如替换属性中的 ${} 占位符、修改作用域、添加属性;
  • 不创建 Bean 实例:仅操作 BeanDefinition(元数据),此时 Bean 尚未实例化;
  • 执行时机:所有 BeanDefinition 注册完成后,Bean 实例化前。

2. 关键实现类解析

(1)PropertySourcesPlaceholderConfigurer—— 替换占位符

PropertySourcesPlaceholderConfigurer 是最常用的实现类,核心功能是替换 BeanDefinition${key} 形式的占位符(如 ${db.url})。

工作流程:

  1. 加载外部配置文件(如 application.properties);
  2. 遍历所有 BeanDefinitionpropertyValues
  3. ${key} 替换为配置文件中的对应值;
  4. 更新 BeanDefinition 的属性值。

示例(XML 配置):

1
2
3
4
5
6
7
8
9
10
11
12
<!-- 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

BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor 的子接口,扩展了 “注册新 BeanDefinition” 的能力,执行顺序先于普通 BeanFactoryPostProcessor

示例(动态注册 BeanDefinition):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Component
public class CustomBeanRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 动态创建UserService的BeanDefinition
BeanDefinition userServiceDef = BeanDefinitionBuilder
.genericBeanDefinition(UserService.class)
.addPropertyReference("userDao", "userDao")
.getBeanDefinition();
// 注册新BeanDefinition(id=dynamicUserService)
registry.registerBeanDefinition("dynamicUserService", userServiceDef);
}

@Override
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 自动匹配构造器(按类型 / 索引 / 名称)。

示例(无参构造器实例化):

1
2
3
4
5
6
7
8
9
// 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 1. 定义FactoryBean
public class UserFactoryBean implements FactoryBean<User> {
@Override
public User getObject() {
return new User("张三", 18); // 生成目标Bean
}

@Override
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
2
3
4
5
6
7
8
9
10
// 1. 创建BeanWrapper(包装实例化后的对象)
BeanWrapper beanWrapper = new BeanWrapperImpl(beanInstance);

// 2. 获取BeanDefinition中的属性值
PropertyValues pvs = userServiceDef.getPropertyValues(); // 含userDao的引用

// 3. 注入属性(处理引用类型:从BeanFactory获取依赖Bean)
beanWrapper.setPropertyValues(pvs);

// 此时,userServiceInstance的userDao属性已注入完成
(3)自动注入的关键:InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessorBeanPostProcessor 的子接口,在属性注入阶段发挥作用,例如:

  • AutowiredAnnotationBeanPostProcessor:处理 @Autowired 注解,扫描字段 / 方法并注入依赖;
  • CommonAnnotationBeanPostProcessor:处理 @Resource 注解。

步骤 3:初始化 —— 增强 Bean(Aware→初始化方法→代理)

属性注入完成后,Spring 对 Bean 执行初始化逻辑,按以下顺序执行:

(1)Aware 接口回调

Bean 若实现 Aware 接口(如 BeanNameAwareBeanFactoryAware),Spring 会注入对应的容器服务:

1
2
3
4
5
6
7
8
9
// 示例:实现BeanNameAware
public class UserService implements BeanNameAware {
private String beanName;

@Override
public void setBeanName(String name) {
this.beanName = name; // Spring 注入当前Bean的id
}
}
(2)BeanPostProcessor 的 postProcessBeforeInitialization

所有 BeanPostProcessor 的前置处理方法,例如:

  • ApplicationContextAwareProcessor:处理 ApplicationContextAware 等接口;
  • 自定义 BeanPostProcessor:修改 Bean 实例(如添加日志增强)。
(3)初始化方法执行(按顺序)
  1. @PostConstruct:JSR-250 注解,Bean 构造后执行;
  2. InitializingBean:Spring 接口,执行 afterPropertiesSet() 方法;
  3. init-method:XML 或 @Bean(initMethod) 指定的自定义初始化方法。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class UserService implements InitializingBean {
@PostConstruct
public void postConstruct() {
System.out.println("1. @PostConstruct 执行");
}

@Override
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:实例化完成后,存入 DefaultListableBeanFactorysingletonObjects 缓存(键:Bean id,值:Bean 实例),后续 getBean() 直接从缓存获取;
  • 原型 Bean:不存入缓存,每次 getBean() 都会重新执行 “实例化→属性注入→初始化” 流程。

关键细节与注意事项

  1. 单例 vs 原型的实例化时机:
    • 单例 Bean:默认在容器启动时实例化(可通过 @Lazy 延迟到首次 getBean());
    • 原型 Bean:仅在调用 getBean() 时实例化。
  2. 循环依赖的解决:
    • Spring 通过 “三级缓存” 解决单例 Bean 的循环依赖(singletonFactoriesearlySingletonObjectssingletonObjects);
    • 原型 Bean 的循环依赖无法解决,会抛出 BeanCurrentlyInCreationException
  3. FactoryBean 的特殊处理:
    • 调用 getBean("factoryBeanId") 时,返回 FactoryBean.getObject() 的结果;
    • 调用 getBean("&factoryBeanId") 时,返回 FactoryBean 本身。

总结:Bean 实例化全流程(精简版)

  1. 配置加载BeanDefinitionReader 读取 XML / 注解,生成 BeanDefinition
  2. 注册蓝图BeanDefinition 注册到 BeanDefinitionRegistry
  3. 增强蓝图BeanFactoryPostProcessor 修改 BeanDefinition(如替换占位符);
  4. 实例化:通过构造器 / 工厂方法创建 Bean 实例;
  5. 属性注入BeanWrapper 注入属性,InstantiationAwareBeanPostProcessor 处理自动注入;
  6. 初始化:Aware 回调→postProcessBeforeInitialization→初始化方法→postProcessAfterInitialization(AOP 代理);
  7. 就绪:单例 Bean 存入缓存,原型 Bean 直接返回

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10