Spring IOC 核心源码解析
一、核心入口
对于新手来说,不用一上来就啃全量源码,先抓住核心入口类 和核心流程 :本文以 Spring 6.x 中基于注解的 IOC 容器入口是 AnnotationConfigApplicationContext,创建容器的核心代码:
ini
// 最简容器初始化代码
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
NotificationController controller = context.getBean(NotificationController.class);
这一行代码背后,就是 IOC 容器的完整生命周期,我们拆解为 4 个核心步骤:
二、IOC 核心流程源码拆解
步骤 1:容器初始化 - 刷新上下文(核心方法:refresh ())
AnnotationConfigApplicationContext 构造方法最终会调用 AbstractApplicationContext 的 refresh() 方法,这是 IOC 容器的 "总开关",核心代码简化如下:
scss
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 1. 准备刷新:初始化环境、校验配置
prepareRefresh();
// 2. 获取 BeanFactory(核心容器),加载 Bean 定义
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 3. 准备 BeanFactory:设置类加载器、注册内置 Bean 等
prepareBeanFactory(beanFactory);
try {
// 4. 后置处理 BeanFactory(扩展点)
postProcessBeanFactory(beanFactory);
// 5. 执行 BeanFactory 后置处理器(扫描并注册 BeanDefinition)
invokeBeanFactoryPostProcessors(beanFactory);
// 6. 注册 Bean 后置处理器(处理注解如@Autowired、@PostConstruct)
registerBeanPostProcessors(beanFactory);
// 7. 初始化消息源(国际化)
initMessageSource();
// 8. 初始化事件广播器
initApplicationEventMulticaster();
// 9. 子类扩展:初始化其他 Bean(如 Web 环境的 ThemeSource)
onRefresh();
// 10. 注册事件监听器
registerListeners();
// 11. 实例化所有非懒加载的单例 Bean(核心!)
finishBeanFactoryInitialization(beanFactory);
// 12. 完成刷新:发布事件、初始化 Lifecycle 处理器
finishRefresh();
} catch (BeansException ex) {
// 异常处理:销毁已创建的 Bean
destroyBeans();
cancelRefresh(ex);
throw ex;
}
}
}
重点关注:步骤 5(扫描 Bean)和步骤 11(实例化 Bean)是 IOC 的核心中的核心。
步骤 2:扫描 Bean - 生成 BeanDefinition
步骤 5 中,ConfigurationClassPostProcessor 会扫描指定包下的注解类(@Component、@Service、@Controller 等),将每个类封装为 BeanDefinition(Bean 定义元信息,包含类名、作用域、依赖等),并存入 BeanFactory 的 beanDefinitionMap 中。核心逻辑在 ClassPathBeanDefinitionScanner 的 doScan() 方法:
ini
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
// 扫描包下的类,生成 BeanDefinition
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
// 设置作用域(默认单例)
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
// 生成 Bean 名称(默认类名首字母小写)
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
// 处理通用注解(如@Lazy、@Primary)
AnnotationConfigUtils.processCommonDefinitionAnnotations(candidate);
// 注册 BeanDefinition 到容器
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
核心概念 :BeanDefinition 是 Spring 对 Bean 的 "描述",容器先存描述,再根据描述创建实例,这是 Spring 灵活扩展的关键。
步骤 3:实例化 Bean - createBean ()
步骤 11 中,DefaultListableBeanFactory 的 preInstantiateSingletons() 方法会遍历所有 BeanDefinition,调用 createBean() 方法创建实例,核心流程:
- 创建 Bean 实例 :通过反射调用构造方法(
instantiateBean()); - 依赖注入 :处理
@Autowired注解,从容器中获取依赖 Bean 并注入(populateBean()); - 初始化 Bean :执行
@PostConstruct注解方法、初始化方法(initializeBean()); - 存入容器 :将创建好的单例 Bean 存入
singletonObjects(单例池)。
核心代码简化:
less
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
try {
// 1. 创建 Bean 实例
Object beanInstance = doCreateBean(beanName, mbd, args);
// 2. 依赖注入 + 初始化
populateBean(beanName, mbd, beanInstance);
exposedObject = initializeBean(beanName, exposedObject, mbd);
return exposedObject;
} catch (BeansException ex) {
destroyBean(beanName, mbd, beanInstance);
throw ex;
}
}
步骤 4:依赖注入 - AutowiredAnnotationBeanPostProcessor
@Autowired 注解的处理核心是 AutowiredAnnotationBeanPostProcessor,它是一个 BeanPostProcessor(Bean 后置处理器),在 populateBean() 阶段执行:
- 扫描 Bean 的字段 / 方法上的
@Autowired注解; - 根据类型 / 名称从容器中查找依赖的 Bean;
- 通过反射注入依赖(支持字段注入、构造器注入、setter 注入)。
三、看源码的建议
- 先跑通最简案例 :写一个只有
AppConfig+NotificationController的最简项目,debug 跟踪AnnotationConfigApplicationContext的创建流程; - 抓核心不贪全:先搞懂「扫描→BeanDefinition→实例化→注入」4 个核心步骤,再看扩展点(后置处理器、生命周期);
📌 关注我 ,每天5分钟,带你从 Java 小白变身编程高手!
👉 点赞 + 关注,让更多小伙伴一起进步!