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 能力)。所以它是 注解驱动 + 不可重复刷新 的轻量上下文。

相关推荐
dadaobusi10 小时前
学习:RV lkvm SBI
java·学习·spring
HEJOO912 小时前
深入理解 Java volatile 关键字:原理、用法与常见误区
java·开发语言·spring
曹牧12 小时前
Java:no content to map due to end of input
java·开发语言
阿维的博客日记13 小时前
Example 类全场景实战指南
java·mybatis
两点王爷13 小时前
SpringBoot 项目集成 GeoServer 源码,实现地图服务发布
java·spring boot·后端
Javatutouhouduan13 小时前
Java如何速通性能优化难题?
java·java面试·jvm调优·后端开发·java程序员·java八股文·java性能优化
lemon_sjdk13 小时前
DOM 节点
java·前端·javascript
leoZ23114 小时前
2026-09-09-springboot-cloud-deploy-pitfalls
java·前端·javascript·vue.js·人工智能·spring boot·后端
驭渊的小故事14 小时前
多线程02
java·开发语言·jvm
随遇而安zx15 小时前
【多线程】---实战:CompletableFuture编排
java·多线程·并发