work hard work smart

专注于Java后端开发。 不断总结,举一反三。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

SpringBoot异常报告器

Posted on 2020-03-01 21:29  work hard work smart  阅读(826)  评论(0编辑  收藏  举报

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) 运行程序。错误输出如下