You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AnnotationConfigApplicationContext时配置属性未加载及上下文初始化器生效问题

AnnotationConfigApplicationContext时配置属性未加载及上下文初始化器生效问题

看起来你踩了原生Spring容器和Spring Boot容器的功能差异坑——直接用AnnotationConfigApplicationContext不会自动启用Spring Boot那套开箱即用的配置机制,咱们一步步来解决这两个问题:

一、配置属性未加载的原因与解决方法

你用SpringApplicationBuilder启动MyTestApplication时,Spring Boot会默默帮你做一堆幕后工作:比如自动加载application.yml到环境中、启用@ConfigurationProperties的绑定处理器、注册相关自动配置后置处理器等等。但AnnotationConfigApplicationContext是原生Spring的容器,它完全不知道这些Spring Boot特有的功能,所以MyConfiguration虽然能被实例化,但属性根本不会被自动绑定。

这里有两种靠谱的解决思路:

方法1:借助SpringApplication构建上下文(推荐)

这种方式最贴近你原来的启动逻辑,能100%复用原有上下文的所有配置,还能直接拿到AnnotationConfigApplicationContext实例:

// 完全复用原来的启动逻辑,包括WebApplicationType和初始化器
SpringApplication app = new SpringApplication(MyTestApplication.class);
app.setWebApplicationType(WebApplicationType.NONE);
app.addInitializers(new ImportantContextInitializer());
// 启动后获取上下文
AnnotationConfigApplicationContext ctx = (AnnotationConfigApplicationContext) app.run();

// 用完记得关闭上下文
// ctx.close();

方法2:手动给原生容器补全Spring Boot特性

如果你一定要纯手动使用AnnotationConfigApplicationContext,得手动补上Spring Boot帮你做的三件事:

  1. 把application.yml加载到容器环境中
  2. 注册处理@ConfigurationProperties绑定的核心后置处理器
  3. 确保你的配置类被正确注册

代码示例:

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();

// 1. 加载application.yml到容器环境
YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
Resource resource = new ClassPathResource("application.yml");
try {
    PropertySource<?> propertySource = loader.load("applicationYml", resource).get(0);
    ctx.getEnvironment().getPropertySources().addLast(propertySource);
} catch (IOException e) {
    throw new RuntimeException("加载application.yml失败", e);
}

// 2. 注册Spring Boot配置属性绑定的核心处理器
ctx.register(ConfigurationPropertiesBindingPostProcessorRegistrar.class);

// 3. 注册你的主配置类(MyTestApplication或MyServicesConfiguration都可以)
ctx.register(MyTestApplication.class);

// 后续处理上下文初始化器后再refresh

二、让ImportantContextInitializer生效的方法

原生AnnotationConfigApplicationContext不会自动识别Spring Boot的ApplicationContextInitializer,你需要在refresh()之前手动把它添加到容器的初始化器列表中:

// 在refresh前添加初始化器
ctx.addApplicationContextInitializer(new ImportantContextInitializer());
// 然后执行上下文刷新
ctx.refresh();

如果你用上面的方法1(借助SpringApplication),直接调用app.addInitializers()就能和原来的启动逻辑完全一致,不用手动处理。

完整手动实现的示例代码

把两个问题的解决逻辑整合到一起,完整的手动实现代码如下:

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();

// 加载application.yml到环境
YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
Resource resource = new ClassPathResource("application.yml");
try {
    PropertySource<?> propertySource = loader.load("applicationYml", resource).get(0);
    ctx.getEnvironment().getPropertySources().addLast(propertySource);
} catch (IOException e) {
    throw new RuntimeException("加载application.yml失败", e);
}

// 注册配置属性绑定处理器
ctx.register(ConfigurationPropertiesBindingPostProcessorRegistrar.class);

// 添加上下文初始化器
ctx.addApplicationContextInitializer(new ImportantContextInitializer());

// 注册主配置类
ctx.register(MyTestApplication.class);

// 刷新上下文
ctx.refresh();

最后提个小建议:如果不是业务必须要用原生AnnotationConfigApplicationContext,优先用方法1的SpringApplication方式,它能帮你避免手动补全特性时遗漏细节(比如Spring Boot的环境后置处理器、配置属性校验器等),减少踩坑概率。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 11:13:03