Spring Boot小组件 - FailureAnalyzer

前言

一个Spring Boot 应用偶尔会因为某些原因启动失败,此时Spring Boot会友好地输出类似于这样一段文字,告诉你发生了什么,甚至应该采取什么行动:

***************************

APPLICATION FAILED TO START

***************************

Description:

Parameter 0 of constructor in com.example.B required a bean of type 'com.example.A' that could not be found.

Action:

Consider defining a bean of type 'com.example.A' in your configuration.

这是怎么做到的呢?或许第一想法是SpringBoot会在出现问题的地方构造这样完整的异常和输出。实际上并非如此,Spring Boot提供了统一的接口进行问题的分析和诊断,这就是org.springframework.boot.diagnostics.FailureAnalyzer 接口。

本文所使用的源码版本为 2.2.2.RELEASE,如有出入请检查版本是否不一致。

从哪开始

已知Spring Boot项目是通过调用SpringApplication#run(java.lang.String...)启动的。我们会发现当启动过程抛出异常时,是这样处理的:

catch (Throwable ex) {
	handleRunFailure(context, ex, exceptionReporters, listeners);
	// ...
}

观察一下找到方法参数中exceptionReporters就是用来报告处理异常的,回过头来寻找其定义,发现其通过SpringFactoriesLoader#loadFactoryNames加载classpath下META-INF中spring.factories里定义的SpringBootExceptionReporter实现类。

一般只有FailureAnalyzers这一个实现类,里面的处理也很简洁:通过SpringFactoriesLoader加载到所有定义的FailureAnalyzer实现,然后稍微prepare一下。分析异常时遍历所有的FailureAnalyzer看谁能分析到问题就好了。分析完呢还要报告分析结果,又是加载了FailureAnalysisReporter所有实现类,然后一个一个报告。通常也只有一个,就是我们在“前言”中看到输出日志的LoggingFailureAnalysisReporter

SpringFactoriesLoader 类似于Java原生的SPI,可以通过编写配置文件为某个接口寻找服务实现。

做一个自己的

如果做一个自己的组件,就可能会遇上需要处理异常并向使用者提供建议的情况。

我们定义一个异常

public class WannaStopException extends RuntimeException {
}

我们定义一个Bean在某(全)种(部)情况下会抛出异常

@Service
public class A {
    public A() {
        throw new WannaStopException();
    }
}

我们定义一个FailureAnalyzer专门处理这个WannaStopException

public class StopFailureAnalyzer extends AbstractFailureAnalyzer<WannaStopException> {
    @Override
    protected FailureAnalysis analyze(Throwable rootFailure, WannaStopException cause) {
        for (StackTraceElement stackTraceElement : cause.getStackTrace()) {
            if (stackTraceElement.getClassName().equals("com.example.flowable.A")) {
                return new FailureAnalysis("A想停止", "别要A了", cause);
            }
        }
        return null;
    }
}

AbstractFailureAnalyzer 帮助我们找到特定异常

接下来我们还要把StopFailureAnalyzer放进spring.factories中,在resources/META-INF/spring.factories(自己建)里添加

org.springframework.boot.diagnostics.FailureAnalyzer=\
  com.example.flowable.StopFailureAnalyzer 

启动这个应用,就能看到如下输出

***************************

APPLICATION FAILED TO START

***************************

Description:

A想停止

Action:

别要A了

另外也注意到FailureAnalysisReporter可以用来向开发进行报警,或者进行一些自动修复操作(如自动回滚)等。

猜你喜欢

转载自www.cnblogs.com/imyijie/p/12695098.html