AnnotationConfigApplicationContext初始化源码详解

  • AnnotationConfigApplicationContext 是 Spring 中基于注解配置的应用上下文实现,其初始化流程严格遵循 Java 类加载机制(父类优先)和 Spring 容器的分层设计。以下从用户触发创建到容器完全就绪,分阶段详细解析。
  • 解析源码目的:熟悉Spring基于注解启动流程,扩展Spring开发使用。
  • 源码位置:
org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(java.lang.Class<?>...)

一、时序图

用户 AnnotationConfigApplicationContext GenericApplicationContext AbstractApplicationContext DefaultListableBeanFactory AnnotatedBeanDefinitionReader ClassPathBeanDefinitionScanner 传入的组件类(如@Configuration类) new AnnotationConfigApplicationContext(ComponentClasses...) 构造方法(Class<?>... componentClasses) 调用父类GenericApplicationContext()构造 调用父类AbstractApplicationContext()构造 初始化resourcePatternResolver(PathMatchingResourcePatternResolver) new DefaultListableBeanFactory() 返回BeanFactory实例(blfInstance) this.beanFactory = blfInstance new AnnotatedBeanDefinitionReader(this) 返回实例 new ClassPathBeanDefinitionScanner(this) 返回实例 register(componentClasses) reader.register(componentClasses) 向blfInstance注册BeanDefinition refresh() blfInstance执行初始化流程(BeanFactoryPostProcessor、Bean实例化等) 调用BeanFactoryPostProcessor处理@Configuration类 实例化非延迟单例Bean(依赖注入、AOP代理) 发布ContextRefreshedEvent 用户 AnnotationConfigApplicationContext GenericApplicationContext AbstractApplicationContext DefaultListableBeanFactory AnnotatedBeanDefinitionReader ClassPathBeanDefinitionScanner 传入的组件类(如@Configuration类)

二、类继承关系

1. AnnotationConfigApplicationContext

在这里插入图片描述

三、源码解析

步骤1:触发容器创建

  • 目标:创建一个基于注解配置的 Spring 应用上下文实例,传入的AppConfig.class(通常是带@Configuration注解的类)将作为容器的配置源。
  • 调用构造函数
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

步骤2:构造函数调用链(父类优先初始化)

  • 根据 Java 类加载机制,子类构造必须先调用父类构造函数(隐式调用super())。因此,AnnotationConfigApplicationContext(以下简称 AAC)的构造流程会先完成父类链的初始化。

1. 父类 AbstractApplicationContext 初始化

  • 调用链:AAC 的父类链为:AAC → GenericApplicationContext → AbstractApplicationContext。
  • AbstractApplicationContext 构造
    • resourcePatternResolver:默认使用PathMatchingResourcePatternResolver,用于解析类路径资源(如classpath*: *.xml)。
public AbstractApplicationContext() {
	// 属性赋值 PathMatchingResourcePatternResolver
	this.resourcePatternResolver = getResourcePatternResolver();
}

2. 父类 GenericApplicationContext 初始化

  • GenericApplicationContext 是AbstractApplicationContext的子类,负责管理BeanFactory(Spring 的核心 Bean 容器)。
  • 创建 DefaultListableBeanFactory
    • 通过new DefaultListableBeanFactory()创建 Spring 的默认 Bean 工厂实例(blfInstance),并赋值给GenericApplicationContext的beanFactory字段。
    • DefaultListableBeanFactory 是 Spring 的核心 Bean 工厂实现,负责存储BeanDefinition(Bean 的元数据)、实例化 Bean、处理依赖注入等。
  • DefaultListableBeanFactory初始化源码详解
public GenericApplicationContext() {
	this.beanFactory = new DefaultListableBeanFactory();
}

3. 子类 AnnotationConfigApplicationContext 构造逻辑

  • 在完成父类初始化后,AAC 开始执行自身的构造逻辑。
  • 初始化注解解析器 AnnotatedBeanDefinitionReader。
    • 通过new AnnotatedBeanDefinitionReader(this)创建实例
    • 解析带注解的类(如@Configuration、@Component、@Service),将其转换为BeanDefinition(Spring 内部对 Bean 的元数据描述)。
    • 自动注册 Spring 内置的注解处理器(如AutowiredAnnotationBeanPostProcessor,用于处理@Autowired依赖注入)。
    • AnnotatedBeanDefinitionReader初始化源码详解
this.reader = new AnnotatedBeanDefinitionReader(this);
  • 初始化类路径扫描器 ClassPathBeanDefinitionScanner。
    • 通过new ClassPathBeanDefinitionScanner(this)创建实例。
    • 扫描指定类路径下的组件类(如通过@ComponentScan注解指定的包),并将符合条件的类(带@Component及其派生注解)注册为BeanDefinition。
    • ClassPathBeanDefinitionScanner初始化源码详解
this.scanner = new ClassPathBeanDefinitionScanner(this);

步骤3:注册提供的配置类

  • 在构造函数的最后一步,AAC 会调用register(ComponentClasses…)方法,将用户传入的配置类(如AppConfig.class)注册到容器中。
  • 具体逻辑
    • AnnotatedBeanDefinitionReader 的register()方法会将配置类解析为BeanDefinition,并存储到DefaultListableBeanFactory的beanDefinitionMap中。
      • BeanDefinition 包含类名(beanClass)、作用域(scope,默认单例)、初始化方法(initMethod)、依赖关系(dependencies)等元数据。
    • Spring BeanDefinition:Bean 的构建蓝图
context.register(AppConfig.class); // 构造函数内部自动调用

步骤4:容器刷新(核心初始化流程)

  • 由于容器刷新内容很多,需要注意的小细节也很多,后续单独解析源码。

四、流程图

AnnotationConfigApplicationContext 初始化
├── 1. 用户触发创建容器
│ └── User → AAC: new AnnotationConfigApplicationContext(ComponentClasses...)

├── 2. AAC 构造函数启动
│ └── AAC: 构造方法 (Class<?>... componentClasses)
│ ├── 2.1 父类构造链初始化(Java 规范:先父类后子类)
│ │ ├── 2.1.1 GAC 父类构造
│ │ │ └── AAC → GAC: 调用父类 GenericApplicationContext () 构造
│ │ │ ├── 2.1.1.1 AACParent 父类构造
│ │ │ │ └── GAC → AACParent: 调用父类 AbstractApplicationContext () 构造
│ │ │ │ └── AACParent: 初始化 resourcePatternResolver(PathMatchingResourcePatternResolver)
│ │ │ ├── 2.1.1.2 GAC 初始化 BeanFactory
│ │ │ │ ├── GAC → BLF: new DefaultListableBeanFactory()
│ │ │ │ │ └── BLF → GAC: 返回 BeanFactory 实例(blfInstance)
│ │ │ │ └── GAC: this.beanFactory = blfInstance
│ │ └── 2.1.2 父类构造完成(GAC、AACParent 初始化完毕)

│ ├── 2.2 子类 AAC 初始化注解处理组件
│ │ ├── 2.2.1 初始化 AnnotatedBeanDefinitionReader
│ │ │ └── AAC → Reader: new AnnotatedBeanDefinitionReader(this)
│ │ │ └── Reader → AAC: 返回实例(用于解析注解类为 BeanDefinition)
│ │ └── 2.2.2 初始化 ClassPathBeanDefinitionScanner
│ │ └── AAC → Scanner: new ClassPathBeanDefinitionScanner(this)
│ │ └── Scanner → AAC: 返回实例(用于扫描类路径组件)

│ ├── 2.3 注册用户传入的组件类
│ │ └── AAC: register(componentClasses)
│ │ └── AAC → Reader: reader.register(componentClasses)
│ │ └── Reader → BLF: 向 blfInstance 注册 BeanDefinition(存储组件类元数据)

│ └── 2.4 容器刷新(核心初始化)
│ └── AAC: refresh()
│ ├── 2.4.1 BLF 执行初始化流程
│ │ └── AAC → BLF: blfInstance 初始化
│ │ ├── 2.4.1.1 调用 BeanFactoryPostProcessor
│ │ │ └── BLF: 处理 @Configuration 类(解析 @Bean、@ComponentScan 等注解)
│ │ └── 2.4.1.2 实例化非延迟单例 Bean
│ │ └── BLF: 完成依赖注入、AOP 代理等逻辑
│ └── 2.4.2 发布容器就绪事件
│ └── AAC: 发布 ContextRefreshedEvent(通知监听器容器初始化完成)

五、总结

  • 父类优先初始化:遵循 Java 类加载机制,先完成父类AbstractApplicationContext和GenericApplicationContext的基础架构初始化(如BeanFactory创建)。
  • 注解驱动:通过AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner解析注解,将配置类和组件类转换为BeanDefinition。

六、带注释的源码地址(5.3.33版本)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值