Spring Boot详细打印启动时异常堆栈信息详析

 更新时间:2019年10月01日 09:04:51   转载 作者:恒宇少年  
这篇文章主要给大家介绍了关于Spring Boot详细打印启动时异常堆栈信息的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring Boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧

前言

SpringBoot在项目启动时如果遇到异常并不能友好的打印出具体的堆栈错误信息,我们只能查看到简单的错误消息,以致于并不能及时解决发生的问题,针对这个问题SpringBoot提供了故障分析仪的概念(failure-analyzer),内部根据不同类型的异常提供了一些实现,我们如果想自定义该怎么去做?

FailureAnalyzer

SpringBoot提供了启动异常分析接口FailureAnalyzer,该接口位于org.springframework.boot.diagnosticspackage内。
内部仅提供一个分析的方法,源码如下所示:

@FunctionalInterface
public interface FailureAnalyzer {

 /**
 * Returns an analysis of the given {@code failure}, or {@code null} if no analysis
 * was possible.
 * @param failure the failure
 * @return the analysis or {@code null}
 */
 FailureAnalysis analyze(Throwable failure);

}

该接口会把遇到的异常对象实例Throwable failure交付给实现类,实现类进行自定义处理。

AbstractFailureAnalyzer

AbstractFailureAnalyzer是FailureAnalyzer的基础实现抽象类,实现了FailureAnalyzer定义的analyze(Throwable failure)方法,并提供了一个指定异常类型的抽象方法analyze(Throwable rootFailure, T cause),源码如下所示:

public abstract class AbstractFailureAnalyzer<T extends Throwable> implements FailureAnalyzer {

 @Override
 public FailureAnalysis analyze(Throwable failure) {
 T cause = findCause(failure, getCauseType());
 if (cause != null) {
  return analyze(failure, cause);
 }
 return null;
 }

 /**
 * Returns an analysis of the given {@code rootFailure}, or {@code null} if no
 * analysis was possible.
 * @param rootFailure the root failure passed to the analyzer
 * @param cause the actual found cause
 * @return the analysis or {@code null}
 */
 protected abstract FailureAnalysis analyze(Throwable rootFailure, T cause);

 /**
 * Return the cause type being handled by the analyzer. By default the class generic
 * is used.
 * @return the cause type
 */
 @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;
 }

}

通过AbstractFailureAnalyzer源码我们可以看到,它在实现于FailureAnalyzer的接口方法内进行了特殊处理,根据getCauseType()方法获取当前类定义的第一个泛型类型,也就是我们需要分析的指定异常类型。

获取泛型异常类型后根据方法findCause判断Throwable是否与泛型异常类型匹配,如果匹配直接返回给SpringBoot进行注册处理。

SpringBoot提供的分析实现

SpringBoot内部通过实现AbstractFailureAnalyzer抽象类定义了一系列的针对性异常类型的启动分析,如下图所示:

指定异常分析

SpringBoot内部提供的启动异常分析都是指定具体的异常类型实现的,最常见的一个错误就是端口号被占用(PortInUseException),虽然SpringBoot内部提供一个这个异常的启动分析,我们也是可以进行替换这一异常分析的,我们只需要创建PortInUseException异常的AbstractFailureAnalyzer,并且实现类注册给SpringBoot即可,实现自定义如下所示:

/**
 * 端口号被占用{@link PortInUseException}异常启动分析
 *
 * @author 恒宇少年
 */
public class PortInUseFailureAnalyzer extends AbstractFailureAnalyzer<PortInUseException> {
 /**
  * logger instance
  */
 static Logger logger = LoggerFactory.getLogger(PortInUseFailureAnalyzer.class);

 @Override
 protected FailureAnalysis analyze(Throwable rootFailure, PortInUseException cause) {
  logger.error("端口被占用。", cause);
  return new FailureAnalysis("端口号:" + cause.getPort() + "被占用", "PortInUseException", rootFailure);
 }
}

注册启动异常分析

在上面我们只是编写了指定异常启动分析,我们接下来需要让它生效,这个生效方式比较特殊,类似于自定义SpringBoot Starter AutoConfiguration的形式,我们需要在META-INF/spring.factories文件内进行定义,如下所示:

org.springframework.boot.diagnostics.FailureAnalyzer=\
 org.minbox.chapter.springboot.failure.analyzer.PortInUseFailureAnalyzer

那我们为什么需要使用这种方式定义呢?

项目启动遇到的异常顺序不能确定,很可能在Spring IOC并未执行初始化之前就出现了异常,我们不能通过@Component注解的形式使其生效,所以SpringBoot提供了通过spring.factories配置文件的方式定义。

启动异常分析继承关系

自定义的运行异常一般都是继承自RuntimeException,如果我们定义一个RuntimeException的异常启动分析实例会是什么效果呢?

/**
 * 项目启动运行时异常{@link RuntimeException}统一启动分析
 *
 * @author 恒宇少年
 */
public class ProjectBootUnifiedFailureAnalyzer extends AbstractFailureAnalyzer<RuntimeException> {
 /**
  * logger instance
  */
 static Logger logger = LoggerFactory.getLogger(ProjectBootUnifiedFailureAnalyzer.class);

 @Override
 protected FailureAnalysis analyze(Throwable rootFailure, RuntimeException cause) {
  logger.error("遇到运行时异常", cause);
  return new FailureAnalysis(cause.getMessage(), "error", rootFailure);
 }
}

将该类也一并注册到spring.factories文件内,如下所示:

org.springframework.boot.diagnostics.FailureAnalyzer=\
 org.minbox.chapter.springboot.failure.analyzer.PortInUseFailureAnalyzer,\
 org.minbox.chapter.springboot.failure.analyzer.ProjectBootUnifiedFailureAnalyzer

运行项目并测试端口号被占用异常我们会发现,并没有执行ProjectBootUnifiedFailureAnalyzer内的analyze方法,而是继续执行了PortInUseFailureAnalyzer类内的方法。

那我们将PortInUseFailureAnalyzer这个启动分析从spring.factories文件内暂时删除掉,再来运行项目我们会发现这时却是会执行ProjectBootUnifiedFailureAnalyzer类内分析方法。

总结

根据本章我们了解了SpringBoot提供的启动异常分析接口以及基本抽象实现类的运作原理,而且启动异常分析存在分析泛型异常类的上下级继承关系,异常子类的启动分析会覆盖掉异常父类的启动分析,如果你想包含全部异常的启动分析可以尝试使用Exception作为AbstractFailureAnalyzer的泛型参数。

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。

相关文章

  • Spring MVC 启动过程源码分析详解

    Spring MVC 启动过程源码分析详解

    这篇文章主要介绍了Spring MVC 启动过程源码分析详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • java判断两个时间是不是同一天的方法

    java判断两个时间是不是同一天的方法

    这篇文章主要介绍了java判断两个时间是不是同一天的方法,需要的朋友可以参考下
    2014-02-02
  • Eclipse中maven的配置详解

    Eclipse中maven的配置详解

    这篇文章主要介绍了Eclipse中maven的配置详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • java对象的序列化和反序列化

    java对象的序列化和反序列化

    这篇文章主要为大家详细介绍了java对象的序列化和反序列化,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • 使用Java编写GUI对话框的教程

    使用Java编写GUI对话框的教程

    这篇文章主要介绍了使用Java编写GUI对话框的教程,是Java图形化编程中的基础知识,需要的朋友可以参考下
    2015-10-10
  • java 实现 stack详解及实例代码

    java 实现 stack详解及实例代码

    这篇文章主要介绍了java 实现 stack详解的相关资料,需要的朋友可以参考下
    2016-09-09
  • java监听器的实现和原理详解

    java监听器的实现和原理详解

    这篇文章主要给大家介绍了关于java监听器实现和原理的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-08-08
  • 四种Java线程池用法解析

    四种Java线程池用法解析

    这篇文章主要为大家解析四种Java线程池用法,内容详细,分析细致,感兴趣的小伙伴们可以参考一下
    2016-04-04
  • java实现把两个有序数组合并到一个数组的实例

    java实现把两个有序数组合并到一个数组的实例

    今天小编就为大家分享一篇java实现把两个有序数组合并到一个数组的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-05-05
  • java关键字final用法知识点

    java关键字final用法知识点

    在本篇文章里小编给大家分享的是关于java关键字final用法知识点以及相关实例内容,有需要的朋友们可以学习下。
    2019-09-09

最新评论