Spring Boot系列之FailureAnalyzer

2022-12-30 08:55:18

概述

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot</artifactId>
</dependency>

功能定位:拦截启动时异常,将异常转换成更加易读的信息并包装成org.springframework.boot.diagnostics.FailureAnalysis对象,监控应用启动过程。

FailureAnalysis是一个POJO:

@Getter
@AllArgsConstructor
public class FailureAnalysis {
    private final String description;
    private final String action;
    private final Throwable cause;
}

FailureAnalyzer接口:

public interface FailureAnalyzer {
    FailureAnalysis analyze(Throwable var1);
}

AbstractFailureAnalyzer 抽象类实现 FailureAnalyzer 接口,SpringBoot 已经提供一系列 AbstractFailureAnalyzer 继承类,在 org.springframework.boot.diagnostics.analyzerorg.springframework.boot.autoconfigure.diagnostics.analyzer包下面

  • BeanCurrentlyInCreationFailureAnalyzer
  • PortInUseFailureAnalyzer
  • NoSuchMethodFailureAnalyzer
  • BindFailureAnalyzer
  • AbstractInjectionFailureAnalyzer
  • NoSuchBeanDefinitionFailureAnalyzer
  • DataSourceBeanCreationFailureAnalyzer
  • HikariDriverConfigurationFailureAnalyzer
  • NoUniqueBeanDefinitionFailureAnalyzer
  • ValidationExceptionFailureAnalyzer
  • ConnectorStartFailureAnalyzer
  • CompatibilityNotMetFailureAnalyzer
  • BeanNotOfRequiredTypeFailureAnalyzer

随着Spring Boot版本的提升,实现类有所新增。

注册启动异常分析

上面只是编写指定异常启动分析,接下来需要让它生效,这个生效方式比较特殊,类似于自定义SpringBoot Starter AutoConfiguration的形式,然后每个FailureAnalyzer都需要配置在META-INF/spring.factories文件中,如:

# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer

那我们为什么需要使用这种方式定义呢?
项目启动遇到的异常顺序不能确定,很可能在Spring IOC并未执行初始化之前就出现了异常,我们不能通过@Component注解的形式使其生效,所以SpringBoot提供了通过spring.factories配置文件的方式定义。

通过FailureAnalyzer接口拦截获取到启动时异常,然后呢,有啥用?不难发现,在同一个包路径下面存在FailureAnalysisReporter接口:

public interface FailureAnalysisReporter {
    void report(FailureAnalysis var1);
}

接口实现类,有所删减:

@NoArgsConstructor
public final class LoggingFailureAnalysisReporter implements FailureAnalysisReporter {

    public void report(FailureAnalysis failureAnalysis) {
		logger.debug("Application failed to start due to an exception", failureAnalysis.getCause());
        logger.error(this.buildMessage(failureAnalysis));
    }

    private String buildMessage(FailureAnalysis failureAnalysis) {
        StringBuilder builder = new StringBuilder();
        builder.append(String.format("%n%n"));
        builder.append(String.format("***************************%n"));
        builder.append(String.format("APPLICATION FAILED TO START%n"));
        builder.append(String.format("***************************%n%n"));
        builder.append(String.format("Description:%n%n"));
        builder.append(String.format("%s%n", failureAnalysis.getDescription()));
        if (StringUtils.hasText(failureAnalysis.getAction())) {
            builder.append(String.format("%nAction:%n%n"));
            builder.append(String.format("%s%n", failureAnalysis.getAction()));
        }
        return builder.toString();
    }
}

到次,发现熟悉的控制台输出:APPLICATION FAILED TO START

使用

自定义类 CustomFailedAnalyzer 实现接口 FailureAnalyzer,重写方法 FailureAnalysis analyze(Throwable failure);
配置文件spring.factories放置在resources/META-INF
org.springframework.boot.diagnostics.FailureAnalyzer=com.awesome.CustomFailedAnalyzer

https://juejin.im/post/5d91b5006fb9a04e3a7f56b4

  • 作者:johnny233
  • 原文链接:https://blog.csdn.net/lonelymanontheway/article/details/119855491
    更新时间:2022-12-30 08:55:18