全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-18 6 分钟 ✍️ juanwangdev

Spring Boot FailureAnalyzer自定义

FailureAnalyzer 用于在启动失败时提供友好的错误分析。

内置FailureAnalyzer

Spring Boot 内置多个分析器:

分析器处理场景
PortInUseFailureAnalyzer端口被占用
DataSourceFailureAnalyzer数据源配置错误
NoSuchBeanDefinitionFailureAnalyzerBean不存在
ValidationExceptionFailureAnalyzer参数校验失败
BindFailureAnalyzer配置绑定失败

自定义FailureAnalyzer

定义异常

Java
public class LicenseExpiredException extends RuntimeException {
    private final String licenseKey;
    private final Date expiredDate;

    public LicenseExpiredException(String licenseKey, Date expiredDate) {
        super("License expired: " + licenseKey);
        this.licenseKey = licenseKey;
        this.expiredDate = expiredDate;
    }

    public String getLicenseKey() { return licenseKey; }
    public Date getExpiredDate() { return expiredDate; }
}

实现分析器

Java
public class LicenseExpiredFailureAnalyzer
        extends AbstractFailureAnalyzer<LicenseExpiredException> {

    @Override
    protected FailureAnalysis analyze(
            Throwable rootFailure,
            LicenseExpiredException cause) {

        return new FailureAnalysis(
            // 问题描述
            String.format("License已过期,Key: %s,过期时间: %s",
                cause.getLicenseKey(),
                new SimpleDateFormat("yyyy-MM-dd").format(cause.getExpiredDate())),

            // 解决建议
            "请联系管理员续期或更新License配置",

            // 原始异常
            cause
        );
    }
}

注册分析器

properties
# META-INF/spring.factories
org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.LicenseExpiredFailureAnalyzer

启动输出示例

Java
***************************
APPLICATION FAILED TO START
***************************

Description:

License已过期,Key: ABC123,过期时间: 2026-01-01

Action:

请联系管理员续期或更新License配置

配置绑定失败分析

Java
public class CustomBindFailureAnalyzer
        extends AbstractFailureAnalyzer<BindException> {

    @Override
    protected FailureAnalysis analyze(
            Throwable rootFailure,
            BindException cause) {

        StringBuilder description = new StringBuilder();
        description.append("配置绑定失败:\n");

        for (FieldError error : cause.getFieldErrors()) {
            description.append(String.format("  - %s: %s (值: %s)\n",
                error.getField(),
                error.getDefaultMessage(),
                error.getRejectedValue()));
        }

        return new FailureAnalysis(
            description.toString(),
            "请检查application.yml中的配置项格式是否正确",
            cause
        );
    }
}

Bean缺失分析

Java
public class MissingBeanFailureAnalyzer
        extends AbstractFailureAnalyzer<NoSuchBeanDefinitionException> {

    @Override
    protected FailureAnalysis analyze(
            Throwable rootFailure,
            NoSuchBeanDefinitionException cause) {

        String beanName = cause.getBeanName();
        Class<?> beanType = cause.getBeanType();

        String description;
        if (beanName != null) {
            description = String.format(
                "未找到名为 '%s' 的Bean,请检查是否已定义或组件扫描路径是否正确",
                beanName);
        } else {
            description = String.format(
                "未找到类型为 '%s' 的Bean,请检查是否添加了相关依赖或配置",
                beanType.getName());
        }

        String action = String.format(
            "建议操作:\n" +
            "  1. 检查是否添加了相关starter依赖\n" +
            "  2. 检查@ComponentScan扫描路径\n" +
            "  3. 检查是否需要@Enable*注解开启功能");

        return new FailureAnalysis(description, action, cause);
    }
}

多异常分析

Java
public class CompositeFailureAnalyzer implements FailureAnalyzer {

    private final List<FailureAnalyzer> analyzers = Arrays.asList(
        new LicenseExpiredFailureAnalyzer(),
        new CustomBindFailureAnalyzer()
    );

    @Override
    public FailureAnalysis analyze(Throwable failure) {
        for (FailureAnalyzer analyzer : analyzers) {
            FailureAnalysis analysis = analyzer.analyze(failure);
            if (analysis != null) {
                return analysis;
            }
        }
        return null;
    }
}

测试FailureAnalyzer

text
class LicenseExpiredFailureAnalyzerTest {

    private final LicenseExpiredFailureAnalyzer analyzer =
        new LicenseExpiredFailureAnalyzer();

    @Test
    void testAnalyze() {
        LicenseExpiredException ex = new LicenseExpiredException(
            "TEST-KEY",
            new Date(System.currentTimeMillis() - 86400000L)
        );

        FailureAnalysis analysis = analyzer.analyze(null, ex);

        assertThat(analysis).isNotNull();
        assertThat(analysis.getDescription()).contains("TEST-KEY");
        assertThat(analysis.getAction()).contains("续期");
    }
}

FailureAnalyzer只处理启动阶段异常,运行时异常需要使用全局异常处理。

要点总结

  • 继承AbstractFailureAnalyzer实现特定异常分析
  • 返回FailureAnalysis包含描述和建议
  • 通过spring.factories注册
  • 提升启动失败错误信息的可读性

📝 发现内容有误?点击此处直接编辑

← 上一篇 Spring Boot EnvironmentPostProcessor扩展
下一篇 → Spring Boot自定义健康指示器
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库