首頁 > 軟體

SpringBoot FailureAnalyzer範例使用教學

2022-12-03 14:01:24

SpringBoot自定義FailureAnalyzer

今天在學習Spring Boot 原始碼的過程中,在spring.factories 檔案中無意中發現了FailureAnalyzer 這個介面。由於之前沒有接觸過,今天來學習一下 FailureAnalyzer 介面的作用。

在學習FailureAnalyzer之前, 我們先看以下截圖

相信Spring的開發者,或多或少的遇到過以上的錯誤。由於埠佔用阻止了應用程式啟動,這跟今天的主角有關係。Spring Boot 應用程式啟動時,FailureAnalyzer介面攔截啟動過程中發生的異常,並終止啟動。

FailureAnalyzer

核心介面定義

package org.springframework.boot.diagnostics;
/**
 * 該介面使用者分析異常堆疊資訊,將其轉換為使用者可讀的物件資訊,通常情況下,物件包含錯誤描述和建議.
 * @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 初始化異常");
    }
}

驗證結果

重新啟動應用程式,出現以下錯誤

到此這篇關於SpringBoot FailureAnalyzer範例使用教學的文章就介紹到這了,更多相關SpringBoot FailureAnalyzer內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com