bigywater.tech
Spring · 85

FailureAnalyzer:启动失败的报错是怎么生成的

启动失败时那一段 APPLICATION FAILED TO START 是哪来的?为什么有的错误有修复建议、有的只有一大串堆栈?怎么给自己的错误也写一个?这篇把几种常见的启动失败都跑一遍,再自己写一个 FailureAnalyzer。

25 个
本 classpath 上登记的 FailureAnalyzer 个数,分布在 5 个 jar
Description + Action
有分析器的启动失败都是这个格式,退出码 1
39 行 / 25 行堆栈
没有登记分析器的异常:控制台行数与其中的堆栈帧行数

常见启动失败

实测 · 本机执行输出
  找不到依赖的 Bean(退出码 1):
    APPLICATION FAILED TO START
    ***************************
    Description:
    Parameter 0 of constructor in demo.NeedsMissing required a bean of type 'demo.MissingDep' that could not be found.
    Action:
    Consider defining a bean of type 'demo.MissingDep' in your configuration.
  同类型有两个 Bean(退出码 1):
    APPLICATION FAILED TO START
    ***************************
    Description:
    Parameter 0 of constructor in demo.NeedsDup required a single bean, but 2 were found:
    	- dup1: defined in file [<jtmp>/x85/out/demo/Dup1.class]
    	- dup2: defined in file [<jtmp>/x85/out/demo/Dup2.class]
    This may be due to missing parameter name information
    Action:
    Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
  构造器循环依赖(退出码 1):
    APPLICATION FAILED TO START
    ***************************
    Description:
    The dependencies of some of the beans in the application context form a cycle:
    ┌─────┐
    |  cycA defined in file [<jtmp>/x85/out/demo/CycA.class]
    ↑     ↓
    |  cycB defined in file [<jtmp>/x85/out/demo/CycB.class]
    └─────┘
    Action:
    Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by set
  @ConfigurationProperties 绑定失败(bp.port=abc)(退出码 1):
    APPLICATION FAILED TO START
    ***************************
    Description:
    Failed to bind properties under 'bp.port' to int:
        Property: bp.port
        Value: "abc"
        Origin: "bp.port" from property source "systemProperties"
        Reason: failed to convert java.lang.String to int (caused by java.lang.NumberFormatException: For input string: "abc")
    Action:
    Update your application's configuration
  @Value 占位符没有值(退出码 1):
    没有失败报告;控制台共 46 行,其中以 at 开头的堆栈帧 32 行;最里面的异常:Caused by: org.springframework.util.PlaceholderResolutionException: Could not resolve placeholder 'nope.value' in value "${nope.value}"
  数据源:有 JDBC 驱动但没配 url(退出码 1):
    APPLICATION FAILED TO START
    ***************************
    Description:
    Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
    Reason: Failed to determine a suitable driver class
    Action:
    Consider the following:
    	If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
    	If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
  端口被占用:
  (先让别的进程占住 53962 端口,退出码 1)
    APPLICATION FAILED TO START
    ***************************
    Description:
    Web server failed to start. Port 53962 was already in use.
    Action:
    Identify and stop the process that's listening on port 53962 or configure this application to listen on another port.

缺 Bean、两个 Bean、循环依赖、绑定失败、数据源、端口占用都有报告;占位符没有值只有堆栈。

分析器从哪来

实测 · 本机执行输出
  扫描 classpath 上全部 jar 的 META-INF/spring.factories,登记在 FailureAnalyzer 名下的类一共 25 个,分布在 5 个 jar 里:
    spring-boot-autoconfigure-4.0.8.jar:2 个,例如 ['NoSuchBeanDefinitionFailureAnalyzer', 'BundleContentNotWatchableFailureAnalyzer']
    spring-boot-web-server-4.0.8.jar:2 个,例如 ['PortInUseFailureAnalyzer', 'MissingWebServerFactoryBeanFailureAnalyzer']
    spring-boot-tomcat-4.0.8.jar:1 个,例如 ['ConnectorStartFailureAnalyzer']
    spring-boot-4.0.8.jar:18 个,例如 ['ConfigDataNotFoundFailureAnalyzer', 'IncompatibleConfigurationFailureAnalyzer', 'NotConstructorBoundInjectionFailureAnalyzer']
    spring-boot-jdbc-4.0.8.jar:2 个,例如 ['DataSourceBeanCreationFailureAnalyzer', 'HikariDriverConfigurationFailureAnalyzer']
  另外 META-INF/spring/*.FailureAnalyzer.imports 形式的文件:0 个

25 个 FailureAnalyzer 登记在 5 个 jar 的 spring.factories 里;认得就出报告,不认得退回堆栈。

自己写分析器

实测 · 本机执行输出
  抛 MyConfigException 的 @PostConstruct,登记了 MyAnalyzer(退出码 1):
    APPLICATION FAILED TO START
    ***************************
    Description:
    应用缺少必需的配置:缺少配置项 app.licence-key
    Action:
    在 application.properties 里加上这个配置项,或者设置对应的环境变量。
  抛 OtherException,没有登记分析器(退出码 1):没有失败报告;控制台共 39 行,其中以 at 开头的堆栈帧 25 行;最里面的异常:Caused by: demo.OtherException: 没人给我写分析器

继承 AbstractFailureAnalyzer,返回 FailureAnalysis,在 spring.factories 里登记。

默认与 --debug

实测 · 本机执行输出
  找不到依赖的 Bean:默认控制台 18 行(其中失败报告 6 行,堆栈帧 0 行);加 --debug 之后 404 行,其中堆栈帧(以 at 开头的行)有 24 行,另外出现了条件评估报告:True
  --debug 之后多出来的内容里,以 Caused by 或异常类名开头的行:
    org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'demo.MissingDep' available: expected at least 1 bean which qualifies as autowire candidate. Dependency anno

默认是整理过的 18 行,--debug 是 404 行并带堆栈和条件评估报告。

分步演示

FailureAnalyzer
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动。被测应用是 spring-boot-starter-webmvc、spring-boot-starter-jdbc 与 mysql-connector-j 的单个程序,用 Boot 默认的日志配置;每个失败场景一个独立 JVM,由属性 x85.case 开关对应的配置;报告取自进程输出里从 APPLICATION FAILED TO START 到 Action 段结束;分析器个数是从 classpath 全部 jar 的 META-INF/spring.factories 里数出来的(没有逐个实例化);端口占用场景用另一个进程以 IPv6 双栈方式占住端口(只占 127.0.0.1 时 Tomcat 照样启动成功)
    • 没有验证:其他 Boot 模块(Data、Security、Kafka 等)带来的 FailureAnalyzer;分析器之间的顺序与 @Order;MissingWebServerFactoryBeanFailureAnalyzer 等没有逐个触发的分析器;FailureAnalysisReporter 的扩展;日志框架不是 Logback 时的输出;原生镜像里的启动失败报告;为什么占位符没有值这种常见错误没有分析器(只观察到没有报告)
    京ICP备2026067502号-1京公网安备11010502063487号