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

Spring Boot重写spring-context初始化器时读取配置属性值报错

问题根因

ApplicationContextInitializer 的执行时机远早于Spring的属性注入流程:Spring Boot启动时,初始化器会在应用上下文刚创建、还未完成Bean实例化、属性注入、配置绑定操作的阶段就触发执行,同时你的WireMockInitializer本身也不是被Spring容器托管的普通Bean,@Value注解没有生效机会,因此wmPort字段为null,调用其intValue()时抛出空指针。

解决方案

方案1:直接从上下文环境读取配置(最适配初始化器场景)

直接通过初始化方法入参的ConfigurableApplicationContext获取环境配置,无需使用@Value注解,修改后代码如下:

public class WireMockInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    private WireMockServer wireMockServer;

    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
        // 直接从上下文环境读取配置,第三个参数为默认值
        Integer wmPort = configurableApplicationContext.getEnvironment()
                .getProperty("wiremock.port", Integer.class, 2222);
        
        // 仅测试环境执行逻辑
        List<String> activeProfiles = Arrays.asList(configurableApplicationContext.getEnvironment().getActiveProfiles());
        if (!activeProfiles.contains("test")) {
            return;
        }
        
        wireMockServer = new WireMockServer(WireMockConfiguration.wireMockConfig().port(wmPort));
        wireMockServer.start();

        configurableApplicationContext.addApplicationListener(applicationEvent -> {
            if (applicationEvent instanceof ContextClosedEvent) {
                wireMockServer.stop();
            }
        });

        configurableApplicationContext.getBeanFactory()
                .registerSingleton("wireMockServer", wireMockServer);
    }
}

额外说明:@ActiveProfiles 放在初始化器上不生效,因此上述代码直接增加了profile判断逻辑。

方案2:改用Spring事件监听实现(更符合Spring常规用法)

如果希望使用@Value注入,可以放弃实现ApplicationContextInitializer,改为用Spring托管Bean+事件监听的方式实现,此时属性注入已经完成,不会出现空指针:

@Component
@ActiveProfiles({"test"})
public class WireMockHolder {
    private WireMockServer wireMockServer;

    @Value("${wiremock.port:2222}")
    private Integer wmPort;

    // 上下文刷新完成后触发,此时@Value已经注入完成
    @EventListener(ContextRefreshedEvent.class)
    public void startWireMock() {
        wireMockServer = new WireMockServer(WireMockConfiguration.wireMockConfig().port(wmPort));
        wireMockServer.start();
    }

    // 上下文关闭时自动停止服务
    @EventListener(ContextClosedEvent.class)
    public void stopWireMock() {
        if (wireMockServer != null) {
            wireMockServer.stop();
        }
    }
}

内容的提问来源于stack exchange,提问作者Prashanth Sams

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 19:12:03