java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot FailureAnalyzer

SpringBoot FailureAnalyzer实例使用教程

作者:u013433591

FailureAnalyzer是一种在启动时拦截exception并将其转换为human-readable消息的好方法,包含在故障分析中。SpringBoot为application context相关的exceptions,JSR-303验证等提供了这样的分析器,实际上很容易创建自己的

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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文