跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
Javajava

SpringBoot 源码解析:应用上下文构造方法详解

综述由AI生成SpringBoot 启动流程中,应用上下文初始化是核心环节。基于 2.7.18 版本源码,深入解析 AnnotationConfigServletWebServerApplicationContext 的构造方法。主要包含两个关键步骤:一是初始化注解 Bean 定义读取器,注册 ConfigurationClassPostProcessor 等内部后置处理器以支持注解解析;二是初始化类路径 Bean 定义扫描器,配置默认过滤器并扫描指定包路径下的组件。这两个组件的构建完成了容器基础环境的搭建,为后续 Bean 加载与依赖注入奠定基础。

魔法巫师发布于 2026/3/23更新于 2026/5/34 浏览
SpringBoot 源码解析:应用上下文构造方法详解

前言

在之前的系列文章中,我们梳理了 SpringApplication 的启动流程,了解了引导上下文、环境准备以及 Bean 工厂的核心组件功能。接下来,我们将深入探讨应用上下文的构造方法,这是 Spring Boot 启动过程中承上启下的关键环节。

本文基于 Spring Boot 2.7.18 版本,重点分析 createApplicationContext() 方法中创建的应用上下文对象及其初始化逻辑。

源码入口

整个启动流程的第 6 步是创建应用程序上下文,核心代码位于 SpringApplication 类的 run 方法中:

// SpringApplication 类方法
public ConfigurableApplicationContext run(String... args) {
    // ... 前置步骤省略 ...
    // 6. 创建应用程序上下文
    context = createApplicationContext();
    // ... 后续步骤省略 ...
}

这里调用的默认实现会实例化 AnnotationConfigServletWebServerApplicationContext。这个类不仅实现了 ApplicationContext 接口,还集成了 Servlet Web Server 的功能,是 Spring Boot Web 应用的标准上下文类型。

无参构造逻辑

当我们查看 AnnotationConfigServletWebServerApplicationContext 的无参构造函数时,会发现它主要做了两件事:初始化注解 Bean 定义读取器和初始化类路径 Bean 定义扫描器。

public class AnnotationConfigServletWebServerApplicationContext 
        extends ServletWebServerApplicationContext implements AnnotationConfigRegistry {

    // 用于读取注解的 Bean 定义读取器
    private final AnnotatedBeanDefinitionReader reader;
    // 用于扫描类路径并注册 Bean 定义的扫描器
    private final ClassPathBeanDefinitionScanner scanner;

    public AnnotationConfigServletWebServerApplicationContext() {
        // 初始化注解 Bean 定义读取器
        this.reader = new AnnotatedBeanDefinitionReader(this);
        // 初始化类路径 Bean 定义扫描器
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }
}

这里的 this 传入子构造器,实际上就是当前应用上下文实例本身。这意味着读取器和扫描器将直接操作当前的容器环境。

一、初始化注解 Bean 定义读取器

AnnotatedBeanDefinitionReader 负责处理带有注解的配置类,将其转换为 Bean 定义并注册到容器中。其构造过程涉及三个关键步骤:获取注册表、获取环境对象、注册后置处理器。

1. Bean 定义注册接口

构造器接收一个 BeanDefinitionRegistry 参数,这通常就是当前的应用上下文。该接口是 Spring 容器管理 Bean 定义的核心,支持动态注册、移除和查询。

public interface BeanDefinitionRegistry extends AliasRegistry {
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
    void removeBeanDefinition(String beanName);
    BeanDefinition getBeanDefinition(String beanName);
    // ... 其他方法
}

2. 获取环境对象 Environment

环境对象提供了配置属性访问能力。如果注册表本身实现了 EnvironmentCapable 接口,则直接从中获取;否则创建一个标准的 StandardEnvironment。

private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    if (registry instanceof EnvironmentCapable) {
        return ((EnvironmentCapable) registry).getEnvironment();
    }
    return new StandardEnvironment();
}

3. 注册注解配置处理器

这是构造过程中最重要的一步。系统会自动注册一系列的后置处理器(PostProcessor),用于处理各种注解逻辑。这些处理器会在后续的 Bean 生命周期中被调用。

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
        BeanDefinitionRegistry registry, @Nullable Object source) {
    
    // 获取默认的 ListableBeanFactory 对象
    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    
    // 设置依赖比较器,支持 @Order 注解排序
    if (beanFactory != null && !(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
        beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
    }
    
    // 设置自动注入候选解析器,处理 @Autowired 等
    if (beanFactory != null && !(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
    }

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

    // 注册 ConfigurationClassPostProcessor,处理 @Configuration、@Bean 等
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 注册 AutowiredAnnotationBeanPostProcessor,处理 @Autowired、@Value
    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 注册 CommonAnnotationBeanPostProcessor,处理 @Resource、@PostConstruct
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 注册 EventListenerMethodProcessor,处理 @EventListener
    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }

    return beanDefs;
}
3.1 获取默认 Bean 工厂

通过 unwrapDefaultListableBeanFactory 方法,从注册表中提取出 DefaultListableBeanFactory 实例。这是 Spring 内部实际管理 Bean 定义和生命周期的核心容器。

@Nullable
private static DefaultListableBeanFactory unwrapDefaultListableBeanFactory(BeanDefinitionRegistry registry) {
    if (registry instanceof DefaultListableBeanFactory) {
        return (DefaultListableBeanFactory) registry;
    } else if (registry instanceof GenericApplicationContext) {
        return ((GenericApplicationContext) registry).getDefaultListableBeanFactory();
    }
    return null;
}

拿到工厂后,设置了两个重要属性:

  • AnnotationAwareOrderComparator:支持 @Order 注解的依赖排序比较器。
  • ContextAnnotationAutowireCandidateResolver:处理 @Autowired 等注解的自动注入候选者解析器。
3.2 注册后置处理器

上面创建的 RootBeanDefinition 都是框架内部使用的基础设施 Bean,角色被设置为 ROLE_INFRASTRUCTURE(值为 2)。用户自定义的 Bean 默认为 ROLE_APPLICATION(值为 0)。

private static BeanDefinitionHolder registerPostProcessor(
        BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
    definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    registry.registerBeanDefinition(beanName, definition);
    return new BeanDefinitionHolder(definition, beanName);
}

这些处理器包括:

  • ConfigurationClassPostProcessor:处理配置类注解。
  • AutowiredAnnotationBeanPostProcessor:处理依赖注入。
  • CommonAnnotationBeanPostProcessor:处理 JSR-250 标准注解。
  • EventListenerMethodProcessor:处理事件监听。

二、初始化类路径 Bean 定义扫描器

ClassPathBeanDefinitionScanner 负责扫描指定包路径下的组件类,并将其注册为 Bean 定义。

1. 注册默认注解过滤器

扫描器在构造时会注册默认的过滤规则,确保能识别常见的 Spring 组件注解。

protected void registerDefaultFilters() {
    // 添加 @Component 注解的过滤器
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    
    // 尝试加载 JSR-250 ManagedBean 注解
    try {
        this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
    } catch (ClassNotFoundException ex) {
        // 忽略不存在的 API
    }
    
    // 尝试加载 JSR-330 Named 注解
    try {
        this.includeFilters.add(new AnnotationTypeFilter(
            ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
    } catch (ClassNotFoundException ex) {
        // 忽略不存在的 API
    }
}

这意味着带有 @Component、@Controller、@Service、@Repository 的类都会被纳入扫描范围。

2. 自定义包扫描

当调用 doScan 方法时,扫描器会遍历指定的基础包路径,查找符合条件的候选组件。

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();

    for (String basePackage : basePackages) {
        // 查找当前包路径下符合条件的候选组件
        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);
            
            // 后处理 Bean 定义
            if (candidate instanceof AbstractBeanDefinition) {
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            if (candidate instanceof AnnotatedBeanDefinition) {
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            
            // 检查并注册
            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;
}

这个过程确保了用户编写的业务组件能够被正确识别、命名并注册到 Spring 容器中。

总结

本文详细拆解了 AnnotationConfigServletWebServerApplicationContext 的构造过程。核心在于初始化两个组件:

  1. 注解 Bean 定义读取器:负责注册框架内部的后置处理器,如 ConfigurationClassPostProcessor 和 AutowiredAnnotationBeanPostProcessor,为后续注解解析打下基础。
  2. 类路径 Bean 定义扫描器:负责扫描指定包路径,识别 @Component 等注解组件,并将其转换为 Bean 定义注册到容器。

这两个组件的初始化标志着 Spring Boot 应用上下文的基本就绪,为后续的刷新(Refresh)和 Bean 加载做好了准备。

目录

  1. 前言
  2. 源码入口
  3. 无参构造逻辑
  4. 一、初始化注解 Bean 定义读取器
  5. 1. Bean 定义注册接口
  6. 2. 获取环境对象 Environment
  7. 3. 注册注解配置处理器
  8. 3.1 获取默认 Bean 工厂
  9. 3.2 注册后置处理器
  10. 二、初始化类路径 Bean 定义扫描器
  11. 1. 注册默认注解过滤器
  12. 2. 自定义包扫描
  13. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • AI-Goofish-Monitor:闲鱼智能监控机器人指南
  • 基于 Java 在高德地图面查询检索中使用 WGS84 坐标的方法
  • GitHub Copilot 学生认证申请及使用指南
  • PyAutoGUI Python 桌面自动化框架实战指南
  • C++ GESP 七级核心考点与算法实战指南
  • Flutter 三方库 flutter_dropzone 的鸿蒙化适配指南
  • MacOS 安装 OpenClaw 并接入飞书机器人
  • 基于大模型 API 与 RAG 知识库构建智能客服机器人实战
  • MySQL 数据类型核心指南:选型、实战与避坑
  • Ubuntu 22.04 下 libwebkit2gtk-4.1-0 安装配置指南
  • 自定义 DialogAlert 对话框并实现复用
  • C++ 模板编程基础:泛型编程入门与实践
  • Windows 系统安装 Linux 子系统(WSL)完整指南
  • 基于 AI 大模型与 Playwright 的 Web UI 自动化测试实践
  • Visual Studio Code 集成 Cursor AI 实战指南
  • 腾讯 WorkBuddy 一键部署与 AI 办公智能体使用指南
  • OpenClaw 爆发推动低代码 AI 从工具赋能到生态重构
  • OpenClaw AI 助手跨设备迁移指南
  • DeepSeek 隐藏玩法与提示词技巧指南
  • Python 处理 Markdown 文件:生成、转换与解析实战

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online