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

为何SpringApplicationBuilder.run要实现线程安全?其设计动机是什么?

SpringApplicationBuilder.run() 线程安全设计动机解析

疑问背景

我了解Spring Boot的SpringApplicationBuilder.run()方法采用了双重检查机制实现线程安全,但有个疑问:即便该类的其他方法并非线程安全,run方法有必要实现线程安全吗?想明确这段代码的设计动机。

核心代码

public ConfigurableApplicationContext run(String... args) {
    if (this.running.get()) {
        // If already created we just return the existing context
        return this.context;
    }
    configureAsChildIfNecessary(args);
    if (this.running.compareAndSet(false, true)) {
        synchronized (this.running) {
            // If not already running copy the sources over and then run.
            this.context = build().run(args);
        }
    }
    return this.context;
}

设计动机解析

  • 杜绝重复创建核心容器:ApplicationContext是Spring应用的核心,创建过程要完成Bean扫描、初始化、依赖注入等大量重操作,成本极高。如果多线程同时调用run,会生成多个独立的容器,不仅浪费系统资源,还会导致Bean多实例、配置逻辑冲突等问题。这段代码通过CAS+双重检查+synchronized的组合,确保只有第一个触发的线程会执行容器创建逻辑,后续线程直接复用已生成的context。

  • 防御性兼容边缘场景:虽然SpringApplicationBuilder的设计初衷是单线程链式调用(比如主线程里先调用各种配置方法,最后调用run),但实际开发中可能出现误操作——比如异步代码里不小心复用了同一个builder实例调用run。给run方法加线程安全保障,能避免这种场景下的崩溃问题,属于典型的防御性编程。

  • 匹配Spring容器的单例语义:Spring应用的ApplicationContext默认是单例语义(一个应用对应一个核心容器),run作为容器创建的入口,必须守住这个语义。而builder的其他非线程安全方法都是构建阶段的配置方法,这些方法的正确用法是在run之前完成调用,多线程调用这些方法本身就不符合构建器模式的使用规范,所以不需要为它们做线程安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 04:31:08