zoukankan      html  css  js  c++  java
  • Spring Boot小组件

    前言

    一个Spring Boot 应用偶尔会因为某些原因启动失败,此时Spring Boot会友好地输出类似于这样一段文字,告诉你发生了什么,甚至应该采取什么行动:

    ***************************

    APPLICATION FAILED TO START

    ***************************

    Description:

    Parameter 0 of constructor in com.example.B required a bean of type 'com.example.A' that could not be found.

    Action:

    Consider defining a bean of type 'com.example.A' in your configuration.

    这是怎么做到的呢?或许第一想法是SpringBoot会在出现问题的地方构造这样完整的异常和输出。实际上并非如此,Spring Boot提供了统一的接口进行问题的分析和诊断,这就是org.springframework.boot.diagnostics.FailureAnalyzer 接口。

    本文所使用的源码版本为 2.2.2.RELEASE,如有出入请检查版本是否不一致。

    从哪开始

    已知Spring Boot项目是通过调用SpringApplication#run(java.lang.String...)启动的。我们会发现当启动过程抛出异常时,是这样处理的:

    catch (Throwable ex) {
    	handleRunFailure(context, ex, exceptionReporters, listeners);
    	// ...
    }
    

    观察一下找到方法参数中exceptionReporters就是用来报告处理异常的,回过头来寻找其定义,发现其通过SpringFactoriesLoader#loadFactoryNames加载classpath下META-INF中spring.factories里定义的SpringBootExceptionReporter实现类。

    一般只有FailureAnalyzers这一个实现类,里面的处理也很简洁:通过SpringFactoriesLoader加载到所有定义的FailureAnalyzer实现,然后稍微prepare一下。分析异常时遍历所有的FailureAnalyzer看谁能分析到问题就好了。分析完呢还要报告分析结果,又是加载了FailureAnalysisReporter所有实现类,然后一个一个报告。通常也只有一个,就是我们在“前言”中看到输出日志的LoggingFailureAnalysisReporter

    SpringFactoriesLoader 类似于Java原生的SPI,可以通过编写配置文件为某个接口寻找服务实现。

    做一个自己的

    如果做一个自己的组件,就可能会遇上需要处理异常并向使用者提供建议的情况。

    我们定义一个异常

    public class WannaStopException extends RuntimeException {
    }
    

    我们定义一个Bean在某(全)种(部)情况下会抛出异常

    @Service
    public class A {
        public A() {
            throw new WannaStopException();
        }
    }
    

    我们定义一个FailureAnalyzer专门处理这个WannaStopException

    public class StopFailureAnalyzer extends AbstractFailureAnalyzer<WannaStopException> {
        @Override
        protected FailureAnalysis analyze(Throwable rootFailure, WannaStopException cause) {
            for (StackTraceElement stackTraceElement : cause.getStackTrace()) {
                if (stackTraceElement.getClassName().equals("com.example.A")) {
                    return new FailureAnalysis("A想停止", "别要A了", cause);
                }
            }
            return null;
        }
    }
    

    AbstractFailureAnalyzer 帮助我们找到特定异常

    接下来我们还要把StopFailureAnalyzer放进spring.factories中,在resources/META-INF/spring.factories(自己建)里添加

    org.springframework.boot.diagnostics.FailureAnalyzer=
      com.example.flowable.StopFailureAnalyzer
    

    启动这个应用,就能看到如下输出

    ***************************

    APPLICATION FAILED TO START

    ***************************

    Description:

    A想停止

    Action:

    别要A了

    另外也注意到FailureAnalysisReporter可以用来向开发进行报警,或者进行一些自动修复操作(如自动回滚)等。

     
  • 相关阅读:
    python-常用数据类型
    python入门篇
    Vue 架构
    Bootstrap Web框架
    策略模式
    Java线程安全总结
    JVM中线程状态转换图
    java 多线程并发系列之 生产者消费者模式的两种实现
    JVM 垃圾回收器详解
    MyISAM和InnoDB索引实现对比
  • 原文地址:https://www.cnblogs.com/imyijie/p/12695098.html
Copyright © 2011-2022 走看看