Spring Boot中的FailureAnalyzer


在这篇文章中,我们将探索  Spring Boot 中的 FailureAnalyzer。我们还将学习在 Spring Boot 中创建自定义故障分析器。
大多数情况下,当我们在服务器启动时遇到异常时,我们需要非常仔细地阅读它以了解发生了什么问题,然后再尝试修复它。
通过FailureAnalyzer,Spring Boot提供了一种在启动时拦截异常的好方法,并将它们转换为更易读的格式(我们不必滚动整个堆栈跟踪)。Spring Boot 附带了许多 FailureAnalyzer,从应用程序上下文相关的异常、JSR-303 验证等开始。
这是一个示例,其中端口 8080 已被使用,当我们尝试在端口 8080 上运行 Spring Boot 应用程序时,PortInUseFailureAnalyzer 拦截了此异常并提供了更具可读性和用户友好性的错误消息。

***************************
APPLICATION FAILED TO START
***************************
Description:
Embedded servlet container failed to start. Port 8080 was already in use.
Action:
Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.

下面是 Spring Boot 提供的几个 FailureAnalyzer 的列表:

  1. PortInUseFailureAnalyzer
  2. NoUniqueBeanDefinitionFailureAnalyzer
  3. BeanCurrentlyInCreationFailureAnalyzer

您可以通过查看org.springframework.boot.diagnosticsSpring Boot 下的包来找到完整的 FailureAnalyzer 列表 。 
Spring Boot 提供了一种简单的方法来创建我们自己的自定义 FailureAnalyzer。
  
1.创建自定义FailureAnalyzer
要创建我们自己的自定义 FailureAnalyzer,我们可以使用 AbstractFailureAnalyzer作为我们方便的扩展点。AbstractFailureAnalyzer将检查是否存在指定的异常,并允许我们的自定义分析器处理它。
让我们在 Spring Boot 中为以下用例创建一个自定义的FailureAnalyzer
  1. 我们将尝试为给定的依赖项注入不同的 bean。
  2. 当我们尝试注入它时,Spring 会抛出 BeanNotOfRequiredTypeException 因为我们试图注入一个不同的 bean。

这是我们的示例 FailureAnalyzer 代码:
public class CustomFailureAnalyzer extends AbstractFailureAnalyzer<BeanNotOfRequiredTypeException> {

    /**
     * Returns an analysis of the given {@code failure}, 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}
     */

    @Override
    protected FailureAnalysis analyze(Throwable rootFailure, BeanNotOfRequiredTypeException cause) {
        String message =
"####################### This is a custom fail Message ################ %n"+
                getDescription(cause);
        return new FailureAnalysis(message , (String)null, cause);
    }

    private String getDescription(BeanNotOfRequiredTypeException ex) {

        StringWriter description = new StringWriter();
        PrintWriter printer = new PrintWriter(description);
        printer.printf(
               
"The bean %s could not be injected"
                        +
"due to %s",
                ex.getBeanName(), ex.getRequiredType().getName());
        return description.toString();
    }
}

重点是analyze()将被触发的方法,并且 Spring Boot 将传递一个 Throwable 对象以及案例(对于我们的案例,Spring 抛出的异常)。我们可以从原因实例中获取详细信息以打印用户友好的消息。

 
2.注册自定义FailureAnalyzer
我们需要一种特殊的方法来向Spring Boot注册我们的自定义 FailureAnalyzer,以便Spring Boot应该能够在系统抛出异常时调用我们的自定义 FailureAnalyzer。我们需要使用spring.factories文件META-INF夹中的属性文件来注册它 。
如果META-INF或spring.factories属性文件不存在,我们需要手动创建它。要注册自定义FailureAnalyzer,请在 spring.factories 中添加以下条目

org.springframework.boot.diagnostics.FailureAnalyzer=\
  com.umeshawasthi.failureanalyzer.CustomFailureAnalyzer

或:
org.springframework.boot.diagnostics.FailureAnalyzer=\
com.umeshawasthi.failureanalyzer.CustomFailureAnalyzer,\ com.umeshawasthi.failureanalyzer.CustomFailureAnalyzer1

 
3.测试

public class AdminDAO {

    public void helloAdmin(){
        System.out.println("Hello Admin");
    }
}
@Repository(
"adminDAO")
public class AdminDAOImpl {

    public void setupAdmin(){
       
//default implimentation
    }
}
@RestController
public class HelloWorldController {
   @Resource(name =
"adminDAO")
   private AdminDAO adminDAO;
   
//some methods
}


Spring会尝试注入类型的adminDao AdminDAOImpl中AdminDAO,因为这些是不兼容的,春天将抛出 BeanNotOfRequiredTypeException。在当前用例中,Spring Boot将检查以确定有效的 FailureAnalyzer已注册,并将信息传递给注册的 FailureAnalyzer。
在我们的例子中,我们已经注册 CustomFailureAnalyzer来处理这种情况,Spring Boot 会将此信息传递给我们的自定义 FailureAnalyzer 以生成更用户友好的消息。

Here is the output when we will run our application