跳至主要內容

Spring 源码学习-Spring创建Bean对象的主流程

科哒大约 3 分钟

流程图核心步骤梳理

根据图示信息,Spring创建Bean的核心流程可分为以下六大阶段,结合三级缓存机制与源码实现,具体流程如下:


1. 配置加载与解析

图示步骤
加载XML解析XML生成BeanDefinition
源码实现

  • 入口ClassPathXmlApplicationContext初始化时触发refresh()
  • 关键类
    • XmlBeanDefinitionReader:读取XML文件
    • BeanDefinitionParserDelegate:解析<bean>标签
  • 生成结果
    每个<bean>标签解析为一个BeanDefinition对象,包含:
class name: "com.example.UserService"
scope: "singleton"
property values: {dataSource → ref="dataSource"}

2. BeanDefinition注册

图示步骤
封装放到容器中(对应图中K:String, V:BeanDefinition
源码实现

  • 注册位置DefaultListableBeanFactory内部的beanDefinitionMap
// Key: Bean名称(String), Value: BeanDefinition对象
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
  • 触发时机
    refresh()obtainFreshBeanFactory()阶段完成注册

3. Bean实例化(核心阶段)

图示步骤
实例化放到容器中(对应图中K:Class, V:Object
源码关键路径

// AbstractAutowireCapableBeanFactory
protected Object doCreateBean(...) {
    // 3.1 实例化对象(反射/CGLIB)
    Object instance = createBeanInstance(beanName, mbd, args);
    
    // 3.2 提前暴露早期引用(解决循环依赖)
    addSingletonFactory(beanName, () -> getEarlyBeanReference(...));
    
    // 3.3 属性注入(DI)
    populateBean(beanName, mbd, instanceWrapper);
    
    // 3.4 初始化(Aware接口、@PostConstruct等)
    initializeBean(beanName, instance, mbd);
    
    // 3.5 完成创建,放入一级缓存
    registerSingleton(beanName, instance);
}

4. 三级缓存机制(解决循环依赖)

图示标注三级缓存K:String, V:ObjectFactory
三级缓存结构

缓存名称存储内容作用阶段
singletonFactoriesObjectFactory(工厂对象)实例化后,初始化前
earlySingletonObjects早期引用(未完成初始化的对象)属性注入阶段
singletonObjects完整Bean(已初始化)初始化完成后

流程示例(A依赖B,B依赖A):

  1. 创建A时,实例化后将其ObjectFactory放入singletonFactories
  2. 填充A的属性时发现需要B,触发B的创建
  3. 创建B时同样将ObjectFactory放入singletonFactories
  4. 填充B的属性时从singletonFactories获取A的ObjectFactory,生成A的早期引用
  5. B完成初始化后放入singletonObjects,A继续完成初始化

5. 容器存储与获取

图示步骤
从容器中获取K:Class, V:Object
源码实现

  • 存储位置DefaultSingletonBeanRegistry的单例池
// Key: Bean名称, Value: 完整Bean实例
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
  • 获取方式
// ApplicationContext接口方法
UserService userService = context.getBean("userService", UserService.class);

6. 完整流程总结

  1. 配置加载:XML → BeanDefinition
  2. 注册定义:beanDefinitionMap存储Bean元数据
  3. 实例化
    • 反射/CGLIB创建对象
    • 提前暴露ObjectFactory(三级缓存)
  4. 依赖注入
    • 解析@Autowired/@Resource等注解
    • 通过三级缓存解决循环依赖
  5. 初始化
    • 调用Aware接口(BeanNameAware等)
    • 执行@PostConstruct和init-method
  6. 容器存储:单例池(singletonObjects)存储完整Bean
  7. 获取使用:通过getBean()从容器获取实例

流程图与源码的对应关系

图示步骤对应源码方法/类技术要点
加载XMLXmlBeanDefinitionReader.loadBeanDefinitions()解析XML的SAX事件模型
生成BeanDefinitionBeanDefinitionParserDelegate.parseBeanDefinitionElement()Bean元数据抽象
实例化AbstractAutowireCapableBeanFactory.createBeanInstance()反射 vs CGLIB策略选择
三级缓存DefaultSingletonBeanRegistry.getSingleton()循环依赖的“先暴露后完善”机制
放到容器中DefaultSingletonBeanRegistry.addSingleton()单例池的线程安全ConcurrentHashMap

学习建议

  1. 调试技巧:在AbstractApplicationContext.refresh()设置断点,观察BeanDefinition加载过程
  2. 关键日志:启用Spring调试日志查看Bean生命周期事件
logging.level.org.springframework.beans=DEBUG
  1. 实践验证:通过以下代码验证循环依赖解决流程:
// 定义两个相互依赖的Bean
@Service
public class A {
    @Autowired private B b;
}
@Service
public class B {
    @Autowired private A a;
}

通过此流程图,可清晰看到Spring如何将XML配置转化为可用的Java对象,并解决复杂的依赖关系问题。这是理解Spring IoC容器设计精髓的关键路径。