SpringBoot FailureAnalyzer實例使用教程
SpringBoot自定義FailureAnalyzer
今天在學(xué)習(xí)Spring Boot 源碼的過程中,在spring.factories 文件中無意中發(fā)現(xiàn)了FailureAnalyzer 這個接口。由于之前沒有接觸過,今天來學(xué)習(xí)一下 FailureAnalyzer 接口的作用。
在學(xué)習(xí)FailureAnalyzer之前, 我們先看以下截圖

相信Spring的開發(fā)者,或多或少的遇到過以上的錯誤。由于端口占用阻止了應(yīng)用程序啟動,這跟今天的主角有關(guān)系。Spring Boot 應(yīng)用程序啟動時,F(xiàn)ailureAnalyzer接口攔截啟動過程中發(fā)生的異常,并終止啟動。
FailureAnalyzer
核心接口定義
package org.springframework.boot.diagnostics;
/**
* 該接口用戶分析異常堆棧信息,將其轉(zhuǎn)換為用戶可讀的對象信息,通常情況下,對象包含錯誤描述和建議.
* @since 1.4.0
*/
@FunctionalInterface
public interface FailureAnalyzer {
/**
* 返回異常錯誤的分析對象,或null
* @param failure the failure
* @return the analysis or {@code null}
*/
FailureAnalysis analyze(Throwable failure);
}
FailureAnalyzer 定義為函數(shù)式接口,因此可以使用Lambda表達(dá)式實現(xiàn)接口,簡化代碼開發(fā)。從定義上可以看出接收 Throwable 類型的參數(shù),返回失敗分析對象 - 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抽象類,最終實現(xiàn)了端口占用報錯信息的分析。
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;
}
/**
* 重新定義鉤子方法,將參數(shù)與泛型對象關(guān)聯(lián),具象化了每一個子類需要實現(xiàn)的功能
*/
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接口的核心抽象類,并重新擴(kuò)展了FailureAnalyzer接口定義的功能。該抽象類實現(xiàn)了Exception對象與失敗分析實現(xiàn)類一一對應(yīng)的功能。如
//PortInUseFailureAnalyzer 負(fù)責(zé)解析 PortInUseException 異常
class PortInUseFailureAnalyzer extends AbstractFailureAnalyzer<PortInUseException>{
...
}
FailureAnalyzer-自定義
上面提到過具體的失敗分析類,是跟每一種Exception類對應(yīng)的,那么我們從定義異常類開始
定義異常類
package com.andy.spring.boot.docker.exception;
public class CustomApplicationException extends RuntimeException {
public CustomApplicationException(String msg){
super(msg);
}
}
異常類定義完畢后,需要定義解析該異常的失敗分析類
實現(xiàn)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, 自定義失敗分析器出現(xiàn)了...!",
"Ummm... 啥都不做,刪庫跑路",
cause);
}
}
接下來,需要Spring
添加spring.factories
接下來,需要Spring Boot 框架識別失敗分析。SPI機(jī)制出場,在resources/META-INF目錄下創(chuàng)建spring.factories文件,內(nèi)容如下
org.springframework.boot.diagnostics.FailureAnalyzer=com.andy.spring.boot.docker.analyzer.CustomApplicationFailureAnalyzer
驗證測試
測試代碼
到目前為止,萬事具備,只欠東風(fēng)。我們需要在應(yīng)用啟動時,拋出自定義異常即可
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 初始化異常");
}
}
驗證結(jié)果
重新啟動應(yīng)用程序,出現(xiàn)以下錯誤

到此這篇關(guān)于SpringBoot FailureAnalyzer實例使用教程的文章就介紹到這了,更多相關(guān)SpringBoot FailureAnalyzer內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Cloud Eureka 服務(wù)上下線監(jiān)控的實現(xiàn)
這篇文章主要介紹了Spring Cloud Eureka 服務(wù)上下線監(jiān)控的實現(xiàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-09-09
spring boot使用thymeleaf為模板的基本步驟介紹
Spring Boot項目的默認(rèn)模板引擎是Thymeleaf,這沒什么好說的,個人覺得也非常好,下面這篇文章主要給大家介紹了關(guān)于spring boot使用thymeleaf為模板的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01
源碼閱讀之storm操作zookeeper-cluster.clj
這篇文章主要介紹了源碼閱讀之storm操作zookeeper-cluster.clj的相關(guān)內(nèi)容,對其源碼進(jìn)行了簡要分析,具有參考意義,需要的朋友可以了解下。2017-10-10
Spring Boot集成教程之異步調(diào)用Async
在項目中,當(dāng)訪問其他人的接口較慢或者做耗時任務(wù)時,不想程序一直卡在耗時任務(wù)上,想程序能夠并行執(zhí)行,我們可以使用多線程來并行的處理任務(wù),也可以使用spring提供的異步處理方式@Async。需要的朋友們下面來一起看看吧。2018-03-03
spring boot+spring cache實現(xiàn)兩級緩存(redis+caffeine)
這篇文章主要介紹了spring boot+spring cache實現(xiàn)兩級緩存(redis+caffeine),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-02-02

