SpringBoot核心特性——自定义启动失败分析
快速启动
创建一个SpringBoot工程,笔者本次学习的SpirngBoot版本为 2.3.1.RELEASE
org.springframework.boot spring-boot-starter-parent 2.3.1.RELEASE
添加相关依赖
org.projectlombok lombok 1.16.18 org.springframework.boot spring-boot-starter-web
编写简单的启动类
package geek.springboot.application; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
启动成功,Tomcat默认监听8080端口
自定义启动失败分析
有时候因为某些原因会导致SpringApplication启动失败,此时可以往SpringBoot中注册自定义失败分析器来进行具体的分析和处理。
1. 实现org.springframework.boot.diagnostics.FailureAnalyzer接口
package geek.springboot.application.failureAnalyzer; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.diagnostics.FailureAnalysis; import org.springframework.boot.diagnostics.FailureAnalyzer; /** * 自定义错误分析 * 通过实现{@link FailureAnalyzer}接口 * @author Bruse */ @Slf4j public class CustomFailureAnalyzer implements FailureAnalyzer { @Override public FailureAnalysis analyze(Throwable failure) { log.error("错误 {}", failure.getMessage()); // 构造一个FailureAnalysis并返回,传参分别是 描述 、措施 、 原因 return new FailureAnalysis(failure.getMessage(), "Please Chang Server Port", failure); } }
org.springframework.boot.diagnostics.FailureAnalyzer=geek.springboot.application.failureAnalyzer.CustomFailureAnalyzer
2.继承 org.springframework.boot.diagnostics.AbstractFailureAnalyzer 类
package geek.springboot.application.failureAnalyzer; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.diagnostics.AbstractFailureAnalyzer; import org.springframework.boot.diagnostics.FailureAnalysis; import org.springframework.context.ApplicationContextException; /** * 自定义错误分析 * 通过继承 {@link org.springframework.boot.diagnostics.AbstractFailureAnalyzer} * * @author Bruse */ @Slf4j public class CustomFailureAnalyzerByExtend extends AbstractFailureAnalyzer { @Override protected FailureAnalysis analyze(Throwable rootFailure, ApplicationContextException cause) { log.error("CustomFailureAnalyzerByExtend Error: {}", cause.getMessage()); return new FailureAnalysis(cause.getMessage(), " You Need To Change Port", cause); } }
org.springframework.boot.diagnostics.FailureAnalyzer= geek.springboot.application.failureAnalyzer.CustomFailureAnalyzerByExtend
AbstractFailureAnalyzer 和 FailureAnalyzer 的区别
AbstractFailureAnalyzer抽象类其实也实现了FailureAnalyzer接口,只是对于要处理的异常更有针对性,即在继承AbstractFailureAnalyzer时,子类可以特别指定哪些异常由其自身进行处理。
AbstractFailureAnalyzer源码部分:
通过analyze()方法不难看出,父类其实会先判断一下实际产生的异常是否匹配泛型中指定的要处理的异常,只有两者匹配,才会真正调用子类实现的analyze()方法进行实际分析。
内置的FailureAnalyzer
SpringBoot默认内置了几种FailureAnalyzer相关实现。以ConnectorStartFailureAnalyzer为例,该类继承自AbstractFailureAnalyzer,并且泛型指定为ConnectorStartFailedException,表示该类实例仅关注ConnectorStartFailedException,仅会对该异常进行尝试分析。
ConnectorStartFailureAnalyzer源码部分:
失败分析报告
以端口占用导致Application启动失败为例,控制台输出如下
可以看到在没有注册自定义的AbstractFailureAnalyzer或FailureAnalyzer的默认情况下,信息输出是交给LoggingFailureAnalysisReporter进行输出的。该类仅实现了FailureAnalysisReporter接口,通过实现该接口的report()方法,进行相关信息输出。
源码片段如下:
当然了,FailureAnalysisReporter也是通过Spring.factories进行注册的
继续深究挖出幕后BOOS—— FailureAnalyzers 类,该类主要职责其实就是调用众多FailureAnalyzer进行analyze并最终report给用户的逻辑。
以下是源码片段:
整体逻辑非常清楚,就是将所有FailureAnalyzer实例进行遍历,逐个调用该analyze()方法,获取到分析结果analysis后,调用所有FailureAnalysisReporter实例的report()方法进行报告。