0源码基础学习Spring源码系列(一)——Bean注入流程
字数 2520 2025-08-11 17:40:22
Spring源码学习:Bean注入流程详解
一、@Autowired与@Resource的区别
核心区别
- @Autowired:先通过类型注入(byType),当存在多个类型时再通过名称注入(byName)
- @Resource:先通过名称注入(byName),当名称不存在或有多个名称时再通过类型注入
注入示例分析
// 接口定义
interface StuService {
String getName();
}
// 实现类1
@Service
class Stu2 implements StuService {
@Override public String getName() { return "stu2"; }
}
// 实现类2
@Service
class Stu3 implements StuService {
@Override public String getName() { return "stu3"; }
}
@Autowired使用场景
- 单一类型直接注入:
@Autowired
SessionUtil sessionUtil; // 只有一个实现类,直接注入
- 多实现类需指定名称:
@Autowired
StuService stu; // 报错,需要指定stu2或stu3
@Autowired
StuService stu2; // 正确注入
@Resource使用场景
- 通过名称注入:
@Resource(name = "stu2")
private StuService stu1;
- 类型不匹配问题:
@Resource
private Stu3 stu2; // 报错,期望Stu3但找到Stu2
Bean命名规则
- 默认命名:类名首字母小写
- 自定义命名:
@Service("stu2") // 自定义bean名称为stu2
@Bean("stu1") // 自定义bean名称为stu1
二、Spring IOC核心概念
1. 配置元数据
描述bean的配置信息,可以是:
- XML文件
- Properties/YAML文件
- 注解(@Service, @Component等)
2. BeanDefinition
- 内存中描述bean的元数据对象
- 相当于bean的生成模板或说明书
- 由BeanDefinitionReader从配置元数据转换而来
3. BeanDefinitionReader
负责将不同格式的配置元数据转换为BeanDefinition:
- XmlBeanDefinitionReader:读取XML配置
- PropertiesBeanDefinitionReader:读取properties配置
- AnnotatedBeanDefinitionReader:读取注解配置
4. BeanFactoryPostProcessor
容器启动阶段的扩展点,用于修改BeanDefinition:
- 修改已注册的BeanDefinition
- 典型应用:属性占位符替换
<property name="url" value="${jdbc.url}"/>
5. BeanDefinitionRegistry
存储BeanDefinition的注册中心,采用KV结构:
- Key: beanName
- Value: BeanDefinition
6. BeanFactory vs FactoryBean
- BeanFactory:bean的工厂,负责创建和管理bean
- FactoryBean:特殊的bean,可以生产其他bean
FactoryBean示例
@Component
class FactoryBeanDemo implements FactoryBean<Student> {
@Override public Student getObject() { return new Student(); }
@Override public Class<?> getObjectType() { return Student.class; }
}
- 获取FactoryBean生产的bean:
@Resource private Object factoryBeanDemo - 获取FactoryBean本身:
@Resource(name = "&factoryBeanDemo")
三、Bean注入流程详解
1. 容器启动阶段
- 读取配置元数据
- 转换为BeanDefinition
- 注册到BeanDefinitionRegistry
- 执行BeanFactoryPostProcessor修改BeanDefinition
2. Bean实例化阶段
核心方法:doGetBean()
主要流程:
- 尝试从缓存获取bean
- 未命中则创建bean
- 处理依赖的bean
- 根据scope创建bean实例
- 属性填充
- 初始化
3. 详细创建流程:doCreateBean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) {
// 1. 实例化bean
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
// 2. 解析注解(@Autowired, @Resource等)
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
// 3. 提前曝光解决循环依赖
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
// 4. 属性填充
populateBean(beanName, mbd, instanceWrapper);
// 5. 初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
// 6. 循环依赖检查
if (earlySingletonExposure) {...}
// 7. 注册bean
registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
}
4. 关键步骤详解
4.1 createBeanInstance:实例化bean
- 解析bean class并验证访问权限
- 处理Supplier回调
- 处理工厂方法
- 自动装配构造函数
- 默认使用无参构造函数
构造函数解析逻辑:
- 查找@Autowired注解的构造方法
- 只有一个有参构造方法时直接使用
- 无特殊标记时使用无参构造方法
最终通过反射创建实例:
ctor.newInstance(argsWithDefaultValues);
4.2 populateBean:属性注入
- 遍历InstantiationAwareBeanPostProcessor
- 处理@Autowired/@Value注解(AutowiredAnnotationBeanPostProcessor)
- 处理@Resource注解(CommonAnnotationBeanPostProcessor)
注入实现:
// 字段注入
field.set(target, getResourceToInject(target, requestingBeanName));
// 方法注入
method.invoke(target, getResourceToInject(target, requestingBeanName));
依赖解析:
resource = beanFactory.resolveBeanByName(name, descriptor);
// 或
resource = factory.getBean(name, element.lookupType);
4.3 initializeBean:初始化bean
- 前置处理(
@PostConstruct方法执行) - 调用初始化方法(InitializingBean.afterPropertiesSet和init-method)
- 后置处理(AOP代理在此发生)
初始化顺序:
- @PostConstruct注解方法
- InitializingBean.afterPropertiesSet()
- init-method指定方法
5. BeanPostProcessor vs BeanFactoryPostProcessor
| 特性 | BeanFactoryPostProcessor | BeanPostProcessor |
|---|---|---|
| 执行阶段 | 容器启动阶段 | 对象实例化阶段 |
| 关注点 | Bean创建前的配置修改 | Bean创建后的功能增强/替换 |
| 典型应用 | 属性占位符替换 | AOP代理、@PostConstruct处理 |
四、总结
Spring Bean注入的核心流程可归纳为:
- 配置解析:将各种配置元数据转换为BeanDefinition
- 实例化:通过反射创建bean实例
- 属性填充:解析并注入依赖属性
- 初始化:执行初始化方法和AOP代理
关键扩展点:
- BeanFactoryPostProcessor:修改BeanDefinition
- BeanPostProcessor:增强bean功能
- FactoryBean:特殊bean的生产工厂
理解这些核心概念和流程,是深入掌握Spring IoC容器的基础。