Spring Boot FailureAnalyzer 应用场景
创始人
2024-03-02 08:21:12

Spring Boot 自定义FailureAnalyzer

今天在学习Spring Boot 源码的过程中,在spring.factories 文件中无意中发现了FailureAnalyzer 这个接口。由于之前没有接触过,今天来学习一下 FailureAnalyzer 接口的作用。

在学习FailureAnalyzer之前, 我们先看以下截图

在这里插入图片描述

相信Spring的开发者,或多或少的遇到过以上的错误。由于端口占用阻止了应用程序启动,这跟今天的主角有关系。Spring Boot 应用程序启动时,FailureAnalyzer接口拦截启动过程中发生的异常,并终止启动。

FailureAnalyzer

核心接口定义

package org.springframework.boot.diagnostics;
/*** 该接口用户分析异常堆栈信息,将其转换为用户可读的对象信息,通常情况下,对象包含错误描述和建议.* @author Andy Wilkinson* @since 1.4.0*/
@FunctionalInterface
public interface FailureAnalyzer {/*** 返回异常错误的分析对象,或null* @param failure the failure* @return the analysis or {@code null}*/FailureAnalysis analyze(Throwable failure);
}

FailureAnalyzer 定义为函数式接口,因此可以使用Lambda表达式实现接口,简化代码开发。从定义上可以看出接收 Throwable 类型的参数,返回失败分析对象 - FailureAnalysis

FailureAnalysis 对象

package org.springframework.boot.diagnostics;/*** The result of analyzing a failure.** @author Andy Wilkinson* @since 1.4.0*/
public class FailureAnalysis {// 问题描述private final String description;// 动作(解决问题的方法)private final String action;// 问题原因private final Throwable cause;public FailureAnalysis(String description, String action, Throwable cause) {this.description = description;this.action = action;this.cause = cause;}// get 方法...
}

PortInUseFailureAnalyzer

以文章开头的报错信息为例,PortInUseFailureAnalyzer 继承AbstractFailureAnalyzer抽象类,最终实现了端口占用报错信息的分析。

package org.springframework.boot.diagnostics.analyzer;import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis;
import org.springframework.boot.web.server.PortInUseException;class PortInUseFailureAnalyzer extends AbstractFailureAnalyzer {@Overrideprotected FailureAnalysis analyze(Throwable rootFailure, PortInUseException cause) {return new FailureAnalysis("Web server failed to start. Port " + cause.getPort() + " was already in use.","Identify and stop the process that's listening on port " + cause.getPort() + " or configure this "+ "application to listen on another port.",cause);}
}

AbstractFailureAnalyzer

public abstract class AbstractFailureAnalyzer implements FailureAnalyzer {@Overridepublic FailureAnalysis analyze(Throwable failure) {T cause = findCause(failure, getCauseType());return (cause != null) ? analyze(failure, cause) : null;}/*** 重新定义钩子方法,将参数与泛型对象关联,具象化了每一个子类需要实现的功能*/protected abstract FailureAnalysis analyze(Throwable rootFailure, T cause);@SuppressWarnings("unchecked")protected Class getCauseType() {return (Class) ResolvableType.forClass(AbstractFailureAnalyzer.class, getClass()).resolveGeneric();}@SuppressWarnings("unchecked")protected final  E findCause(Throwable failure, Class type) {while (failure != null) {if (type.isInstance(failure)) {return (E) failure;}failure = failure.getCause();}return null;}
}

FailureAnalyzer接口的核心抽象类,并重新扩展了FailureAnalyzer接口定义的功能。该抽象类实现了Exception对象与失败分析实现类一一对应的功能。如

//PortInUseFailureAnalyzer 负责解析 PortInUseException 异常
class PortInUseFailureAnalyzer extends AbstractFailureAnalyzer{...
}

FailureAnalyzer-自定义

上面提到过具体的失败分析类,是跟每一种Exception类对应的,那么我们从定义异常类开始

定义异常类

package com.andy.spring.boot.docker.exception;public class CustomApplicationException extends RuntimeException {public CustomApplicationException(String msg){super(msg);}
}

异常类定义完毕后,需要定义解析该异常的失败分析类

实现FailureAnalyzer

package com.andy.spring.boot.docker.analyzer;import com.andy.spring.boot.docker.exception.CustomApplicationException;
import org.springframework.boot.diagnostics.AbstractFailureAnalyzer;
import org.springframework.boot.diagnostics.FailureAnalysis;public class CustomApplicationFailureAnalyzer extends AbstractFailureAnalyzer {@Overrideprotected FailureAnalysis analyze(Throwable rootFailure, CustomApplicationException cause) {return new FailureAnalysis("Yeah, 自定义失败分析器出现了...!","Ummm... 啥都不做,删库跑路",cause);}
}

接下来,需要Spring

添加spring.factories

接下来,需要Spring Boot 框架识别失败分析。SPI机制出场,在resources/META-INF目录下创建spring.factories文件,内容如下

org.springframework.boot.diagnostics.FailureAnalyzer=com.andy.spring.boot.docker.analyzer.CustomApplicationFailureAnalyzer

验证测试

测试代码

到目前为止,万事具备,只欠东风。我们需要在应用启动时,抛出自定义异常即可

package com.andy.spring.boot.docker.service;import com.andy.spring.boot.docker.exception.CustomApplicationException;
import org.springframework.stereotype.Component;@Component
public class CacheService {public CacheService() {throw new CustomApplicationException("bean 初始化异常");}}

验证结果

重新启动应用程序,出现以下错误

在这里插入图片描述

相关内容

热门资讯

北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...