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

为何Spring Boot DevTools会导致main方法执行两次?

嘿,这个问题我之前帮好几个开发者解决过,其实是Spring Boot DevTools的Restart功能在搞鬼,我给你理清楚原因和解决办法:

问题原因

DevTools的核心功能之一是快速重启,为了实现这个功能,它会使用双类加载器机制:

  • 一个BaseClassLoader用来加载第三方依赖库(这些库很少变动)
  • 一个RestartClassLoader用来加载你的应用代码(方便修改后快速重启)

当你启动应用时,JVM会先通过原始类加载器执行一次main方法,之后DevTools会用RestartClassLoader重新加载应用类并再次执行main方法,这就导致你的System.out.println("test")被执行了两次——不管你把它放在main方法内部,还是类的静态初始化块(也就是你说的main方法外部)里,都会因为类被加载两次而触发两次输出。

解决办法

根据你的需求,有几个不同的方案可选:

1. 直接禁用Restart功能

如果你不需要DevTools的热重启功能,或者可以接受用其他方式替代,直接在配置文件里关闭它:
在application.properties中添加:

spring.devtools.restart.enabled=false

或者在application.yml中:

spring:
  devtools:
    restart:
      enabled: false

这样DevTools就不会创建额外的类加载器,你的代码只会被执行一次。

2. 保留DevTools功能,调整代码执行时机

如果你还想保留热部署等功能,可以把需要执行的代码放到Spring应用上下文初始化完成后的回调里,比如实现ApplicationRunner接口:

import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class YourApplication {

    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }

    @Bean
    public ApplicationRunner startupRunner() {
        return args -> {
            System.out.println("test");
        };
    }
}

这个回调只会在Spring容器完全启动后执行一次,不会被DevTools的类加载机制影响。

3. 检查IDE启动配置(可选)

偶尔也会出现IDE误触发两次启动的情况,比如同时运行了main类和Spring Boot插件的启动任务。你可以打开IDE的运行配置,确认只有一个启动项在运行。

补充说明

这其实不是DevTools的bug,而是它为了实现快速重启而设计的特性。双类加载器让DevTools可以在你修改代码后,只重新加载应用类而不用重启整个JVM,大大提升开发效率,但代价就是启动时会有一次额外的类加载和main方法执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:20:53