SpringBoot之自定义启动异常堆栈信息打印方式

网友投稿 449 2022-10-07


SpringBoot之自定义启动异常堆栈信息打印方式

在SpringBoot项目启动过程中,当一些配置或者其他错误信息会有一些的规范的提示信息

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

APPLICATION FAILED TO START

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

Description:

Web server 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.

在SpringBoot 中其实现原理是什么,我们该如何自定义异常信息呢

1、SpringBoot异常处理的源码分析

在springboot启动的核心方法run中会加载所有的SpringBootExceptionReporter

exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,

new Class[] { ConfigurableApplicationContext.class }, context);

调用了getSpringFactoriesInstances方法

private Collection getSpringFactoriesInstances(Class type, Class>[] parameterTypes, Object... args) {

ClassLoader classLoader = getClassLoader();

// Use names and ensure unique to protect against duplicates

Set names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));

List instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);

AnnotationAwareOrderComparator.sort(instances);

return instances;

}

其主要通过Spring的Factories机制来加载

public ConfigurableApplicationContext run(String... args) {

StopWatch stopWatch = new StopWatch();

stopWatch.start();

ConfigurableApplicationContext context = null;

Collection exceptionReporters = new ArrayList<>();

configureHeadlessProperty();

SpringApplicationRunListeners listeners = getRunListeners(args);

listeners.starting();

try {

ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);

configureIgnoreBeanInfo(environment);

Banner printedBanner = printBanner(environment);

context = createApplicationContext();

exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,

new Class[] { ConfigurableApplicationContext.class }, context);

prepareContext(context, environment, listeners, applicationArguments, printedBanner);

refreshContext(context);

afterRefresh(context, applicationArguments);

stopWatch.stop();

if (this.logStartupInfo) {

new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);

}

listeners.started(context);

callRunners(context, applicationArguments);

}

catch (Throwable ex) {

//异常捕获中,向用户打印异常信息

handleRunFailure(context, ex, exceptionReporters, listeners);

throw new IllegalStateException(ex);

}

try {

listeners.running(context);

}

catch (Throwable ex) {

handleRunFailure(context, ex, exceptionReporters, null);

throw new IllegalStateException(ex);

}

return context;

}

在try catch中,catch会打印异常信息

private void handleRunFailure(ConfigurableApplicationContext context, Throwable exception,

Collection exceptionReporters, SpringApplicationRunListeners listeners) {

try {

try {

handleExitCode(context, exception);

if (listeners != null) {

http:// listeners.failed(context, exception);

}

}

finally {

reportFailure(exceptionReporters, exception);

if (context != null) {

context.close();

}

}

}

catch (Exception ex) {

logger.warn("Unable to close ApplicationContext", ex);

}

ReflectionUtils.rethrowRuntimeException(exception);

}

private void reportFailure(Collection exceptionReporters, Throwable failure) {

try {

for (SpringBootExceptionReporter reporter : exceptionReporters) {

if (reporter.reportException(failure)) {

registerLoggedException(failure);

return;

}

}

}

catch (Throwable ex) {

// Continue with normal handling of the original failure

}

if (logger.isErrorEnabled()) {

logger.error("Application run failed", failure);

registerLoggedException(failure);

}

}

遍历exceptionReporters,打印日常信息

SpringBootExceptionReporter是一个回调接口,用于支持对SpringApplication启动错误的自定义报告。里面就一个报告启动失败的方法。

其实现类:org.springframework.boot.diagnostics.FailureAnalyzers

用于触发从spring.factories加载的FailureAnalyzer和FailureAnalysisReporter实例。

2、如何自定义异常信息

/**

*

*

*

*

* @author: xuwd

* @time: 2020/11/16 10:52

*/

public class WannaStopException extends RuntimeException {

}

自定义异常信息打印

public class StopFailureAnalyzer

extends AbstractFailureAnalyzer {

@Override

protected FailureAnalysis analyze(Throwable rootFailure, WannaStopException cause) {

for (StackTraceElement stackTraceElement : cause.getStackTrace()) {

if (stackTraceElement.getClassName().equals("com.pigx.demo.Config21")) {

return new FailureAnalysis("A想停止", "别要A了", cause);

}

}

return null;

}

}

接下来令他生效,通过上面分析可以可看出需要通过AutoConfigurationImportSelector,类似于自定义SpringBoot Starter AutoConfiguration的形式,我们需要在META-INF/spring.factories文件内进行定义,如下所示:

接着在合适的地方抛出WannaStopException 异常

总结

在springboot 启动过程中会先对异常信息进行补捕获,对进行日志格式处理的日志进行处理;其核心是通过SpringBootExceptionReporter回调及sping-spi bean的管理。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:密信技术隆重推出零信任安全解决方案暨网站改版(腾讯零信任安全解决方案)
下一篇:BB射龙门稳赢方法心得无人不晓,必胜策略堪称最屌!(射龙门怎么赢)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~