Spring Boot FailureAnalyzer 应用场景

news2024/10/5 10:07:20

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<PortInUseException> {

	@Override
	protected 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<T extends Throwable> implements FailureAnalyzer {

	@Override
	public 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<? extends T> getCauseType() {
		return (Class<? extends T>) ResolvableType.forClass(AbstractFailureAnalyzer.class, getClass()).resolveGeneric();
	}

	@SuppressWarnings("unchecked")
	protected final <E extends Throwable> E findCause(Throwable failure, Class<E> 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<PortInUseException>{
  ...
}

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<CustomApplicationException> {
    @Override
    protected 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 初始化异常");
    }

}

验证结果

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

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/47661.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spark 3.0 - 8.ML Pipeline 之决策树原理与实战

目录 一.引言 二.决策树基础-信息熵 三.决策树的算法基础 - ID3 算法 四.ML 中决策树的构建 1.信息增益计算 2.连续属性划分 五.ML 决策树实战 1.Libsvm 数据与加载 2.StringIndexer 3.VectorIndexer 4.构建决策树与 Pipeline 5.测试与评估 6.获取决策树 六.总结…

【学习笔记67】JavaScript中的闭包

一、认识函数的过程 1. 定义 在堆内存中开辟一段内存空间(XF001)把函数体的内容&#xff0c;完全百分百的照抄一份&#xff0c;存放在内存空间中(XF001)把内存空间的地址(XF001) 赋值给函数名2. 调用 根据函数名内存储的地址 (XF001) &#xff0c;去堆内存中找到对应函数会去…

Nginx安装Openresty加载Lua代码

1、下载 VM环境&#xff1a;ubuntu 16 http://openresty.org/cn/download.html 我选择的是截图红框的那个版本&#xff0c;其他高级的版本&#xff0c;我编译的时候都会报错&#xff0c;所以选择了这个版本&#xff0c;大家编译失败的时候不要放弃&#xff0c;继续选择其他版…

【PS-8】选区

目录 矩形选框工具 先选区再按【shift】&#xff0c;正方形选区 选区的同时按【ALT】&#xff0c;从中心点选区 选区时按【shiftalt】&#xff0c;从中心点建立正方形选区 模式1&#xff1a;添加到选区 模式2&#xff1a;新选区 模式3&#xff1a; 从选区减去 模式4&am…

《C++Primer》-1-前序与基础第I部分重点

文章目录第一章 开始1. c之与其他语言的优点&#xff1f;2. c语言的组成3. 标准输入输出cin、cout4. include格式第二章 变量和基本类型1. 无符号数的使用注意2. 初始化注意事项3. 声明与定义4. 标识符的下划线规则5. &引用、取地址&、指针的区别6. 如何理解“因为引用…

Rainbow Brackets的配色修改和使用

修改配色&#xff1a;&#xff09; 敲好看内&#xff01;&#xff01; 记得每个都要改噢&#xff01; 5分别对应的是&#xff1a; 圆括号 方括号 波形括号 尖括号 6分别对应的是&#xff1a; ECB1E9 F6F0A9 78B8EF F3BBA2 A9D57E 使用方式 Ctrl 鼠标右键&#xff1a;高亮{}…

C++ Reference: Standard C++ Library reference: Containers: list: list: end

C官网参考链接&#xff1a;https://cplusplus.com/reference/list/list/end/ 公有成员函数 <list> std::list::end C98 iterator end(); const_iterator end() const; C11 iterator end() noexcept; const_iterator end() const noexcept; 返回结束迭代器 返回一个指向…

企业日常公关如何抵御负面信息的入侵?

如今&#xff0c;互联网时代信息传播速度极快&#xff0c;这使得宣传工作效率倍增&#xff0c;也给企业舆情管理带来一定的挑战。舆情优化搞得好&#xff0c;企业宣传工作事半功倍&#xff0c;网络舆论走向负面的话&#xff0c;则对宣传工作非常不利&#xff0c;会导致推广效果…

Echart 柱状图,X轴斜着展示

option { color: [‘#3398DB’], tooltip: { trigger: ‘axis’, axisPointer: { // 坐标轴指示器&#xff0c;坐标轴触发有效 type: ‘shadow’ // 默认为直线&#xff0c;可选为&#xff1a;‘line’ | ‘shadow’ } }, grid: { left: ‘3%’, right: ‘4%’, bottom: ‘3%’…

go-zero服务自动收集线上问题线上实战

前言 ​ 对于pprof&#xff0c;相信熟悉go语言的程序员基本都不陌生&#xff0c;一般线上的问题都是靠它可以快速定位。但是实际项目中&#xff0c;很多时候我们为了性能都不会开启它&#xff0c;但是出了问题又要靠它来分析。好在go-zero已经帮我们很好的集成进来了&#xff…

Leu-Trp-Leu-COOH,42293-99-2

编号: 122381中文名称: 三肽Leu-Trp-Leu英文名: Leu-Trp-LeuCAS号: 42293-99-2单字母: H2N-LWL-OH三字母: H2N-Leu-Trp-Leu-COOH氨基酸个数: 3分子式: C23H34N4O4平均分子量: 430.54精确分子量: 430.26等电点(PI): 6.11pH7.0时的净电荷数: -0.02平均亲水性: -2.3333333333333疏…

[附源码]计算机毕业设计springboot环境保护宣传网站

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Windows中睡眠和休眠的区别

休眠一般是笔记本电脑才有的功能&#xff0c;睡眠是几乎所有电脑都有 一、系统层面的理解 1.1 睡眠 睡眠状态下&#xff0c;电脑只会消耗很少的电量&#xff0c;电脑可更快启动&#xff0c;并且可以立即返回到离开的位置。因此&#xff0c;使用者不必担心由于电池电量耗尽而丢…

国外Essay写作怎么让内容丰富起来?

在国外大学&#xff0c;写Essay是很多课程常用的考核方式&#xff0c;这种形式也非常考察同学们的综合能力。但对于本身英语就是第二语言的我们&#xff0c;有时候会觉得困难&#xff0c;有时候拖到最后匆忙交上去一篇&#xff0c;当然没有办法得到好分数。今天我们就来看一看如…

后端存储实战课总结(上)

创建和更新订单 表设计 最少应该有以下几张表&#xff1a; 订单主表&#xff1a;保存订单基本信息订单商品表&#xff1a;保存订单中的商品信息订单支付表&#xff1a;保存订单支付和退款信息订单优惠表&#xff1a;保存订单的优惠信息 订单主表和字表是一对多关系&#xf…

android Framework 中用到了哪些跨进程通信方式?

文章目录Linux 有哪些跨进程的通信方式&#xff1f;管道本地 Socket共享内存信号Linux 有哪些跨进程的通信方式&#xff1f; Binder 机制是Android基于Linux的一种独特的IPC机制。我们常用的AMS&#xff0c;PMS 等都是通过Binder机制来完成跨进程通信的&#xff0c;那么除了Bin…

维格云连接功能日志入门教程

目录 维格云连接功能简介 维格云连接功能效果 涉及功能范围 注意事项 维格云连接功能简介 应用内「数据管理——概览」界面,新增了连接功能日志模块,便于查看连接功能的执行结果、排查问题。 维格云连接功能效果 鼠标移动至目标日志,点击“查看数据”可以跳转至对应数据…

求树的直径算法以及证明

以下为两次dfs&#xff08;bfs&#xff09;的做法以及正确性证明。 算法步骤 &#xff08;1&#xff09;任取树上一点S&#xff0c;以S为源点BFS得S到各个顶点的d值&#xff1b; &#xff08;2&#xff09;取d值最大者之一为P&#xff0c;再以P为源点BFS得P到各个顶点的d值&am…

Metabase学习教程:仪表盘-7

使用Metabase构建记录查找工具 如何使用Metabase构建内部查找工具来快速查找有关客户、订单或其他数据的详细信息。 我们写过人们使用Metabase的一些有趣的方式其中之一是使用Metabase作为内部或后台应用程序的解决方案&#xff0c;例如客户查找工具。您不必构建定制页面来查…

惠普笔记本重装系统后没有声音如何解决

​最近很多小伙伴又开始了网上冲浪的生活,但是电脑用久了难免会发生一些故障的问题,最近就有些小伙伴重装系统之后问小编自己的电脑没有声音的问题?不要慌?接下来小编教你惠普笔记本重装系统后没有声音的解决方法. 工具/原料&#xff1a; 系统版本&#xff1a;win7系统 型…