SpringBoot异常报告器(九)

1、接口规范

@FunctionalInterface

public interface SpringBootExceptionReporter {


    /**

     * Report a startup failure to the user.

     * @param failure the source failure

     * @return {@code true} if the failure was reported or {@code false} if default

     * reporting should occur.

     */

    boolean reportException(Throwable failure);


}

 

2、进入run方法

 

3、进入getSpringFactoriesInstances方法。用来获取spring.factoryies中类型为SpringBootExceptionReporter的配置。

 

 Spring.facories中对SpringBootExceptionReporter的配置如下

 

4、然后使用createSpringFactoriesInstances创建实例

 

 创建实例的方法如下BeanUtils.instantiateClass

 

 

5、进入FailureAnalyzers类的构造函数

 

6、然后进入loadFailureAnalyzers方法。获取analyzerName,遍历analyzerNames,增加到analyzers变量中

 

 有以下几个analyzerNames

 

6、下面模拟异常实战

1) 我们将端口改为808080808,然后启动项目

 

2) 运行到checkPort抛出异常

 

3) 抛出异常后,run方法里处理异常

 

4) 进入handleRunFailure方法 

 首先进入handleExitCode方法

这里exitCode返回0

然后listeners不为空,发送failed广播

 

5) 进入reportFailure方法

6)然后调用context.close方法

 

close方法先调用doClose方法,然后移除钩子方法。

 

 

 doClose方法。发布shoutdown广播,关闭一些bean和工厂bean,方便垃圾回收。

protected void doClose() {
        // Check whether an actual close attempt is necessary...
        if (this.active.get() && this.closed.compareAndSet(false, true)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Closing " + this);
            }
 
            LiveBeansView.unregisterApplicationContext(this);
 
            try {
                // Publish shutdown event.
                publishEvent(new ContextClosedEvent(this));
            }
            catch (Throwable ex) {
                logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
            }
 
            // Stop all Lifecycle beans, to avoid delays during individual destruction.
            if (this.lifecycleProcessor != null) {
                try {
                    this.lifecycleProcessor.onClose();
                }
                catch (Throwable ex) {
                    logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
                }
            }
 
            // Destroy all cached singletons in the context's BeanFactory.
            destroyBeans();
 
            // Close the state of this context itself.
            closeBeanFactory();
 
            // Let subclasses do some final clean-up if they wish...
            onClose();
 
            // Reset local application listeners to pre-refresh state.
            if (this.earlyApplicationListeners != null) {
                this.applicationListeners.clear();
                this.applicationListeners.addAll(this.earlyApplicationListeners);
            }
 
            // Switch to inactive.
            this.active.set(false);
        }
    }

  

 钩子方法

在JVM退出时,调用这个方法

public static void main(String[] args) {

       System.out.println("hello");

       Thread close_jvm = new Thread(()-> System.out.println("close jvm"));

       Runtime.getRuntime().addShutdownHook(close_jvm);

       System.out.println("world");

   }

运行结果如下:

hello

world

close jvm

  

6) 最终进入FailureAnalyzers类的reportException异常

 

7) 进入report方法

 

 8) 最终进入LoggingFailureAnalysisReporter方法,打印异常

 

 9) 异常信息如下:

 

7、自定义异常报告

1)、创建自定义报告异常类

public class MyExceptionReporter  implements SpringBootExceptionReporter{



    private ConfigurableApplicationContext context;


    public MyExceptionReporter(ConfigurableApplicationContext context) {

        this.context = context;

    }


    @Override

    public boolean reportException(Throwable failure) {

        if(failure instanceof UnsatisfiedDependencyException){

            UnsatisfiedDependencyException exception = (UnsatisfiedDependencyException)failure;

            System.out.println("no such bean " + exception.getInjectionPoint().getField().getName());

        }

        return false;

    }

}

 

2) 模拟异常 创建Solid类

public class Solid {

} 

 

然后引入Solid

这样引用肯定会抛出异常

 

3) 运行程序。错误输出如下

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值