真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

[SpringBoot]源碼分析SpringBoot的異常處理機制

微信號:GitShare
微信公眾號:愛折騰的稻草
如有問題或建議,請在公眾號留言[1]

站在用戶的角度思考問題,與客戶深入溝通,找到霍爾果斯網(wǎng)站設(shè)計與霍爾果斯網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:成都網(wǎng)站建設(shè)、成都網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、國際域名空間、網(wǎng)絡(luò)空間、企業(yè)郵箱。業(yè)務(wù)覆蓋霍爾果斯地區(qū)。

前續(xù)

為幫助廣大SpringBoot用戶達到“知其然,更需知其所以然”的境界,作者將通過SpringBoot系列文章全方位對SpringBoot2.0.0.RELEASE版本深入分解剖析,讓您深刻的理解其內(nèi)部工作原理。

正文

在SpringBoot啟動時,會查找并加載所有可用的SpringBootExceptionReporter,其源碼如下:

//7 使用SpringFactoriesLoader在應(yīng)用的classpath中查找并加載所有可用的SpringBootExceptionReporter
exceptionReporters = getSpringFactoriesInstances(
        SpringBootExceptionReporter.class,
        new Class[] { ConfigurableApplicationContext.class }, context);

繼續(xù)查看getSpringFactoriesInstances方法源碼:

private  Collection getSpringFactoriesInstances(Class type,
        Class[] parameterTypes, Object... args) {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    //查找并加載classpath路徑下META-INF/spring.factories中配置的SpringBootExceptionReporter的所有名稱
    Set names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    //實例化所有的SpringBootExceptionReporter
    List instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    //排序
    AnnotationAwareOrderComparator.sort(instances);
    //返回結(jié)果
    return instances;
}

代碼來看不難,也是通過Spring的Factories機制來加載,之前的文章中已經(jīng)詳細講解過其過程。

SpringBootExceptionReporter
@FunctionalInterface
public interface SpringBootExceptionReporter {

    /**
     * 向用戶報告啟動失敗。
     */
    boolean reportException(Throwable failure);

}
  • SpringBootExceptionReporter是一個回調(diào)接口,用于支持對SpringApplication啟動錯誤的自定義報告。
    里面就一個報告啟動失敗的方法。

  • 其實現(xiàn)類:org.springframework.boot.diagnostics.FailureAnalyzers  
    用于觸發(fā)從spring.factories加載的FailureAnalyzer和FailureAnalysisReporter實例。

FailureAnalyzers
1、實例化FailureAnalyzers
FailureAnalyzers(ConfigurableApplicationContext context) {
    this(context, null);
}

FailureAnalyzers(ConfigurableApplicationContext context, ClassLoader classLoader) {
    Assert.notNull(context, "Context must not be null");
    this.classLoader = (classLoader == null ? context.getClassLoader() : classLoader);
    this.analyzers = loadFailureAnalyzers(this.classLoader);
    prepareFailureAnalyzers(this.analyzers, context);
}
  • 獲取類加載器

  • 加載并實例化所有的FailureAnalyzer  
    通過Spring的Factories機制來查找和加載所有的FailureAnalyzer,
    加載/META/spring.factories 中的org.springframework.boot.diagnostics.FailureAnalyzer配置如下:

# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer
  • 準(zhǔn)備所有的FailureAnalyzer

private void prepareAnalyzer(ConfigurableApplicationContext context,
        FailureAnalyzer analyzer) {
    if (analyzer instanceof BeanFactoryAware) {
        ((BeanFactoryAware) analyzer).setBeanFactory(context.getBeanFactory());
    }
    if (analyzer instanceof EnvironmentAware) {
        ((EnvironmentAware) analyzer).setEnvironment(context.getEnvironment());
    }
}

準(zhǔn)備階段:根據(jù)FailureAnalyzer的類型,設(shè)置其BeanFactory或者Environment屬性值。

2、FailureAnalyzer
@FunctionalInterface
public interface FailureAnalyzer {

    /**
     * 返回給定故障的分析,如果不無法分析,則返回null。
     */
    FailureAnalysis analyze(Throwable failure);

}

用于分析故障并提供可以顯示給用戶的診斷信息。

3、AbstractFailureAnalyzer

FailureAnalyzer的抽象基類,是個泛型類,泛型參數(shù)為Throwable的子類.其實現(xiàn)了analyze方法,源碼如下:

@Override
public FailureAnalysis analyze(Throwable failure) {
    // 1. 獲得failure中的異常堆棧中是type類型的異常
    T cause = findCause(failure, getCauseType());
    if (cause != null) {
        // 2. 如果不等于null,則進行分析
        return analyze(failure, cause);
    }
    // 3. 無法分析,則返回null
    return null;
}
  • 獲得failure中的異常堆棧中是type類型的異常。

protected final  E findCause(Throwable failure, Class type) {
    while (failure != null) {
        if (type.isInstance(failure)) {
            return (E) failure;
        }
        failure = failure.getCause();
    }
    return null;
}
  • AbstractFailureAnalyzer的具體實現(xiàn)  

3.1、AbstractInjectionFailureAnalyzer:用來對注入異常進行分析的抽象基類。    
3.2、BeanCurrentlyInCreationFailureAnalyzer:針對BeanCurrentlyInCreationException.對BeanCurrentlyInCreationException(循環(huán)依賴)進行分析。    
3.3、BeanNotOfRequiredTypeFailureAnalyzer:針對BeanNotOfRequiredTypeException異常進行分析。  
3.4、BindFailureAnalyzer:針對BindException異常進行分析。  
3.5、BindValidationFailureAnalyzer :針對BindValidationException或者BindException異常進行分析。
3.6、ConnectorStartFailureAnalyzer:針對ConnectorStartFailedException(tomcat端口占用時拋出)異常進行分析。  
3.7、DataSourceBeanCreationFailureAnalyzer:針對DataSourceBeanCreationException異常進行分析。  
3.8、HikariDriverConfigurationFailureAnalyzer:它對使用不支持的“dataSourceClassName”屬性導(dǎo)致的Hikari配置失敗進行分析。  
3.9、InvalidConfigurationPropertyNameFailureAnalyzer:針對InvalidConfigurationPropertyNameException異常進行分析。  
3.10、InvalidConfigurationPropertyValueFailureAnalyzer:針對InvalidConfigurationPropertyValueException異常進行分析。  
3.11、NoUniqueBeanDefinitionFailureAnalyzer:針對NoUniqueBeanDefinitionException異常進行分析,且實現(xiàn)了BeanFactoryAware接口。  
3.12、PortInUseFailureAnalyzer:針對PortInUseException(jetty,undertow 容器啟動時端口占用時拋出)異常進行分析。
3.13、UnboundConfigurationPropertyFailureAnalyzer:針對BindException異常進行分析。  
3.14、ValidationExceptionFailureAnalyzer:泛型參數(shù)為ValidationException(當(dāng)使用validation相關(guān)的注解,但是沒有加入相關(guān)實現(xiàn)時觸發(fā),一般不容易觸發(fā),因為一旦加入spring-boot-starter-web依賴,就會加入hibernate-validator)。
4、失敗報告(FailureAnalysisReporter)
@FunctionalInterface
public interface FailureAnalysisReporter {

    /**
     * 將失敗結(jié)果(failureAnalysis)報告給用戶
     */
    void report(FailureAnalysis analysis);

}
  • 失敗結(jié)果報告接口,將失敗結(jié)果信息報告給用戶

  • 其實現(xiàn)類:LoggingFailureAnalysisReporter

public final class LoggingFailureAnalysisReporter implements FailureAnalysisReporter {

    private static final Log logger = LogFactory
            .getLog(LoggingFailureAnalysisReporter.class);

    @Override
    public void report(FailureAnalysis failureAnalysis) {
        if (logger.isDebugEnabled()) {
            logger.debug("Application failed to start due to an exception",
                    failureAnalysis.getCause());
        }
        if (logger.isErrorEnabled()) {
            logger.error(buildMessage(failureAnalysis));
        }
    }

    private String buildMessage(FailureAnalysis failureAnalysis) {
        StringBuilder builder = new StringBuilder();
        builder.append(String.format("%n%n"));
        builder.append(String.format("***************************%n"));
        builder.append(String.format("APPLICATION FAILED TO START%n"));
        builder.append(String.format("***************************%n%n"));
        builder.append(String.format("Description:%n%n"));
        builder.append(String.format("%s%n", failureAnalysis.getDescription()));
        if (StringUtils.hasText(failureAnalysis.getAction())) {
            builder.append(String.format("%nAction:%n%n"));
            builder.append(String.format("%s%n", failureAnalysis.getAction()));
        }
        return builder.toString();
    }

}

通過日志的方式進行打印失敗錯誤信息。

小結(jié)

Spring的代碼使用了很多設(shè)計模式,所以閱讀起來總是繞來繞去,個人感覺其可讀性比較差。今天原本是想畫出異常處理機制的相關(guān)類圖,但是發(fā)現(xiàn)這里的接口和類的關(guān)系都比較簡單,所以就偷懶。如果您通過本文講解,還不是很清晰的話,您可以將其類圖畫出來,那樣會幫助您理解。

后記

為幫助廣大SpringBoot用戶達到“知其然,更需知其所以然”的境界,作者將通過SpringBoot系列文章全方位對SpringBoot2.0.0.RELEASE版本深入分解剖析,讓您深刻的理解其內(nèi)部工作原理。

本系列歷史文章列表
  • 1、[SpringBoot]利用SpringBoot快速構(gòu)建并啟動項目

  • 2、[SpringBoot]詳解SpringBoot應(yīng)用的啟動過程

  • 3、[SpringBoot]深入淺出剖析SpringBoot的應(yīng)用類型識別機制

  • 4、[SpringBoot]深入淺出剖析SpringBoot中Spring Factories機制

  • 5、[SpringBoot]詳解SpringBoot中SpringApplication的run方法的前三步

  • 6、[SpringBoot]圖解Spring的Environment機制

  • 7、[SpringBoot]源碼解析SpringBoot應(yīng)用Environment的構(gòu)造過程

  • 8、[SpringBoot]源碼解析SpringBoot的Banner機制

  • 9、[SpringBoot]圖解SpringBoot的應(yīng)用上下文機制

[SpringBoot]源碼分析SpringBoot的異常處理機制

本文題目:[SpringBoot]源碼分析SpringBoot的異常處理機制
轉(zhuǎn)載注明:http://weahome.cn/article/pdedcc.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部