Spring框架的AnnotationConfigApplicationContext类启动的流程

AnnotationConfigApplicationContext 启动流程

一、入口:构造器调用

AnnotationConfigApplicationContext

java 复制代码
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    this();                  // 步骤1:无参构造
    register(componentClasses);  // 步骤2:注册配置类
    refresh();               // 步骤3:刷新容器(核心)
}

二、this() ------ 初始化基础组件

AnnotationConfigApplicationContext调用父类 GenericApplicationContext 的无参构造,并初始化两个核心组件:

java 复制代码
public AnnotationConfigApplicationContext() {
    this.reader = new AnnotatedBeanDefinitionReader(this);  // 注解读取器
    this.scanner = new ClassPathBeanDefinitionScanner(this); // 类路径扫描器
}

在父类 GenericApplicationContext中,会创建内部 DefaultListableBeanFactory :

js 复制代码
public GenericApplicationContext() {
    this.beanFactory = new DefaultListableBeanFactory();
}

关键点: AnnotatedBeanDefinitionReader 构造时会通过 AnnotationConfigUtils 注册一批基础后处理器(如 ConfigurationClassPostProcessor 、 AutowiredAnnotationBeanPostProcessor 等)到 BeanFactory。

三、register(componentClasses) ------ 注册 BeanDefinition

AnnotationConfigApplicationContext 委托给 reader :

js 复制代码
public void register(Class<?>... componentClasses) {
    this.reader.register(componentClasses);  // 解析 @Configuration/@Component 注册为 BeanDefinition
}

此时只是把 Config.class 注册为一个 BeanDefinition, 尚未实例化 。

四、refresh() ------ 核心容器刷新(模板方法)

真正干活的是 AbstractApplicationContext ,流程如下:

js 复制代码
public void refresh() {
    startupShutdownLock.lock();           // 加锁,防止并发启动/关闭
    prepareRefresh();                     // 1. 准备刷新:设置启动时间、active 标志
    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();  // 2. 获取内部 BeanFactory
    prepareBeanFactory(beanFactory);      // 3. 准备 BeanFactory:注册 ApplicationContextAwareProcessor 等

    postProcessBeanFactory(beanFactory);  // 4. 子类扩展点(GenericApplicationContext 为空实现)
    invokeBeanFactoryPostProcessors(beanFactory);  // 5. 执行 BeanFactoryPostProcessor(核心!)
    registerBeanPostProcessors(beanFactory);       // 6. 注册 BeanPostProcessor

    initMessageSource();                  // 7. 初始化消息源(国际化)
    initApplicationEventMulticaster();    // 8. 初始化事件广播器
    onRefresh();                          // 9. 子类扩展点(初始化特殊 bean)
    registerListeners();                  // 10. 注册 ApplicationListener

    finishBeanFactoryInitialization(beanFactory);  // 11. 实例化所有非懒加载单例(核心!)
    finishRefresh();                      // 12. 发布 ContextRefreshedEvent
}

几个关键步骤详解

步骤 2: obtainFreshBeanFactory() 触发 GenericApplicationContext.java#L289-L295 的 refreshBeanFactory() ,仅校验 refreshed 原子标志(只能刷新一次):

js 复制代码
protected final void refreshBeanFactory() {
    if (!this.refreshed.compareAndSet(false, true)) {
        throw new IllegalStateException("...just call 'refresh' once");
    }
    this.beanFactory.setSerializationId(getId());
}

步骤 5: invokeBeanFactoryPostProcessors(beanFactory) 这是注解配置的核心: ConfigurationClassPostProcessor 会解析 @Configuration 类、 @ComponentScan 、 @Bean 方法、 @Import 等,把所有相关类补充注册为 BeanDefinition。

步骤 11: finishBeanFactoryInitialization(beanFactory) 触发所有非懒加载单例的实例化与依赖注入(包括构造器注入、 @Autowired 、 InitializingBean 、 init-method 等)。此时 serviceImpl 、 AopDemoDao 等 bean 才真正被创建。

步骤 12: finishRefresh() 发布 ContextRefreshedEvent ,触发所有监听器。

五、流程时序总结

scss 复制代码
new AnnotationConfigApplicationContext(Config.class)
    │
    ├─ this()                                  // 父类 GenericApplicationContext 创
    建 beanFactory
    │   └─ new AnnotatedBeanDefinitionReader(this)  // 注册基础后处理器
    │   └─ new ClassPathBeanDefinitionScanner(this)
    │
    ├─ register(Config.class)                  // 注册 Config 为 BeanDefinition
    │   └─ reader.register(...)
    │
    └─ refresh()                               // 容器真正启动
        ├─ prepareRefresh()                    // 设 active=true
        ├─ obtainFreshBeanFactory()             // 校验只刷新一次
        ├─ prepareBeanFactory()                // 注册 Aware 处理器
        ├─ invokeBeanFactoryPostProcessors()   // ConfigurationClassPostProcessor 
        解析 @Configuration
        ├─ registerBeanPostProcessors()        // 注册 BeanPostProcessor(AOP 代理在
        此介入)
        ├─ initMessageSource() / initApplicationEventMulticaster()
        ├─ onRefresh()                         // 子类扩展
        ├─ registerListeners()
        ├─ finishBeanFactoryInitialization()   // ★ 实例化所有单例 bean
        └─ finishRefresh()                    // 发布 ContextRefreshedEvent

类继承结构

复制代码
BeanFactory
  └─ HierarchicalBeanFactory
      └─ ListableBeanFactory
          └─ ConfigurableBeanFactory
              └─ AbstractRefreshableBeanFactory / DefaultListableBeanFactory
                  └─ GenericApplicationContext  ← 
                  AnnotationConfigApplicationContext 的父类
                      └─ AnnotationConfigApplicationContext

AnnotationConfigApplicationContext 继承 GenericApplicationContext (持有 DefaultListableBeanFactory ),并实现 AnnotationConfigRegistry (提供 register / scan 能力)。所以它是 注解驱动 + 不可重复刷新 的轻量上下文。

相关推荐
AI人工智能+电脑小能手2 小时前
大白话说Java设计模式-26-策略模式(业务实战篇)
java·spring·设计模式·策略模式·支付系统·算法切换
不是光头 强2 小时前
Java 后端 AI 技术选型与学习路线
java·人工智能·学习
paopaokaka_luck3 小时前
基于springboot3+vue3的文山民族文化资源展示与推广平台(协同过滤算法、Echarts 图形化分析)
java·前端·spring boot·学习·echarts
eralong3 小时前
Java IO 与 NIO
java·后端
Jesse_EC3 小时前
我给消息推送加了 Publisher Confirm,然后亲手引入了一个竞态
java
S3rein3 小时前
JAVA多线程手撕
java·多线程
用户8181870627463 小时前
第7章 死锁排查实录:jstack定位死锁的完整流程
java·后端
刀锋00013 小时前
Java 工程师转 AI Agent 最短路径:用 Spring 的思维理解 Spring AI 2.0(附 LangChain4j 对照)
java·人工智能·spring boot·spring·ai agent
喵同志不止步于码农3 小时前
Java Caffeine 快速入门
java·开发语言·后端·并发·缓存一致性