跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

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

深入分析 SpringBoot 应用上下文 AnnotationConfigServletWebServerApplicationContext 的构造过程。重点阐述初始化注解 Bean 定义读取器与类路径 Bean 定义扫描器的核心逻辑,包括环境获取、后置处理器注册及组件扫描机制,揭示 Spring 容器启动时 Bean 定义的加载原理。

数字游民发布于 2026/4/7更新于 2026/5/2416 浏览
SpringBoot 源码解析:应用上下文 AnnotationConfigServletWebServerApplicationContext 构造方法

前言

在前文中,我们了解了应用上下文、Bean 工厂以及 Bean 定义的核心组件功能。接下来,我们将深入探讨应用上下文的构造方法。

SpringBoot 版本 2.7.18 中,SpringApplication 的 run 方法执行逻辑包含创建应用程序上下文这一步骤。本文将详细介绍这一环节的实现细节。

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

源码入口

核心内容在于 new AnnotationConfigServletWebServerApplicationContext() 的调用。

无参构造函数如下:

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 即 Application 上下文本身,用于构建内部的读取器和扫描器。

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

AnnotatedBeanDefinitionReader 的构造过程主要涉及三个关键点:获取注册表、获取环境对象、注册注解配置处理器。

public class AnnotatedBeanDefinitionReader {
    private final BeanDefinitionRegistry registry;
    private ConditionEvaluator conditionEvaluator;

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
        this(registry, getOrCreateEnvironment(registry));
    }

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
        // 注册注解配置处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }
}

1. BeanDefinitionRegistry(Bean 定义注册接口)

这里的注册表就是当前应用上下文实例。它是 Spring 容器中管理 Bean 定义的核心接口,支持动态注册、移除、查询和别名管理。

public interface BeanDefinitionRegistry extends AliasRegistry {
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException;
    void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
    boolean containsBeanDefinition(String beanName);
    String[] getBeanDefinitionNames();
    int getBeanDefinitionCount();
    boolean isBeanNameInUse(String beanName);
}

2. 获取环境对象 Environment

在创建应用上下文之前,环境对象通常已经准备就绪。如果注册表实现了 EnvironmentCapable 接口,则直接获取其中的 Environment;否则创建一个标准的 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. 注册注解配置处理器

这是构造过程中的关键一步,用于处理各种注解配置。

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

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

    // 注册 ConfigurationClassPostProcessor,处理 @Configuration 等注解
    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 注解
    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 等注解
    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 工厂

通过反射或类型转换从注册表中获取 DefaultListableBeanFactory。这个工厂负责管理和创建应用上下文中的所有 Bean,维护着 beanDefinitionMap 缓存。

3.2 注册后置处理器(注册 Bean 定义)

这里创建的 RootBeanDefinition 主要用于 Spring 内部处理注解配置,角色被设置为 ROLE_INFRASTRUCTURE。

  • ConfigurationClassPostProcessor:处理 @Configuration、@Bean、@Import、@ComponentScan 等注解。
  • AutowiredAnnotationBeanPostProcessor:处理 @Autowired、@Value 注解。
  • CommonAnnotationBeanPostProcessor:处理 @PostConstruct、@PreDestroy、@Resource 注解。
  • EventListenerMethodProcessor:处理 @EventListener 注解。

注册完成后,这些定义会被添加到应用上下文的缓存中。

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

1. 注册默认注解过滤器

ClassPathBeanDefinitionScanner 的构造方法会注册默认的注解扫描过滤器,确保能识别特定注解。

protected void registerDefaultFilters() {
    // 添加 @Component 注解的过滤器
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    
    try {
        // 尝试加载 JSR-250 ManagedBean 注解
        this.includeFilters.add(new AnnotationTypeFilter(ClassUtils.forName("javax.annotation.ManagedBean", getClassLoader()), false));
    } catch (ClassNotFoundException ex) {
        // 忽略不支持的情况
    }
    
    try {
        // 尝试加载 JSR-330 Named 注解
        this.includeFilters.add(new AnnotationTypeFilter(ClassUtils.forName("javax.inject.Named", getClassLoader()), false));
    } catch (ClassNotFoundException ex) {
        // 忽略不支持的情况
    }
}

2. 自定义包扫描

此方法将在后续通过传入包路径调用,返回注册的 Bean 定义集合。

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());
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);

            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;
}

总结

本文详细介绍了 SpringBoot 应用上下文 AnnotationConfigServletWebServerApplicationContext 的构造方法。核心在于初始化两个重要组件:一是注解 Bean 定义读取器,负责创建特殊 Bean 定义(如后置处理器)以处理各类注解配置;二是类路径 Bean 定义扫描器,负责扫描指定路径下的组件并将其转换为 Bean 定义注册到容器中。这两个组件共同奠定了 Spring 容器启动的基础。

  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

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

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

更多推荐文章

查看全部
  • 算法题:接雨水问题详解与动态规划解法
  • AI原生应用开发:Llama模型的10个高级用法
  • AIGC 智能推荐技术拆解与前端落地实践
  • 设计模式实战:策略模式实现算法解耦与灵活替换
  • llama-cpp-python 本地部署与实战指南
  • MCP 实战:利用 Figma AI Bridge 自动生成前端代码
  • PyWebIO 表格数据展示与高效可视化实践
  • 错排问题解析:定义、公式推导与编程实战
  • C++ STL 常用容器入门与用法详解
  • Ubuntu 22.04 下 libwebkit2gtk-4.1-0 安装避坑指南
  • Win10 禁用 Microsoft 365 Copilot 弹窗的 6 种方案
  • Python pandas 数据透视表 pivot_table 详解与实战
  • 智谱 AI 发布 GLM-4 基座大模型,性能逼近 GPT-4
  • CloudStudio 部署 DeepSeek-R1 大模型及远程访问配置指南
  • PX4 开源飞控系统概述及入门指南
  • MCP 插件配置实战:browser-tools-mcp 集成指南
  • Python 流程控制详解:条件与循环语句及实战
  • 二分查找:山峰数组的峰顶索引与寻找峰值
  • WebStorm 安装与配置详细教程
  • OpenWrt 固件编译:从环境搭建到多架构适配

相关免费在线工具

  • 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