SpringBoot
在项目启动时如果遇到异常并不能友好的打印出具体的堆栈错误信息,有的一些异常根本看不出来异常的点只是看到容器的一堆stop日志,以致于并不能及时解决发生的问题,针对这个问题SpringBoot提供了故障分析仪的概念(failure-analyzer),内部根据不同类型的异常提供了一些实现。
FailureAnalyzer
SpringBoot
提供了启动异常分析接口FailureAnalyzer
, 在org.springframework.boot.diagnostics
这个包里面的一个接口,接口定义如下:
@FunctionalInterface
public interface FailureAnalyzer {
/**
* Returns an analysis of the given {@code failure}, or {@code null} if no analysis
* was possible.
* @param failure the failure
* @return the analysis or {@code null}
*/
FailureAnalysis analyze(Throwable failure);
}
该接口返回了一个FailureAnalysis对象,我们看到这个接口有一个抽象的实现类: AbstractFailureAnalyzer
,代码如下:
public abstract class AbstractFailureAnalyzer<T extends Throwable>
implements FailureAnalyzer {
@Override
public FailureAnalysis analyze(Throwable failure) {
T cause = findCause(failure, getCauseType());
if (cause != null) {
return analyze(failure, cause);
}
return null;
}
/**
* Returns an analysis of the given {@code rootFailure}, or {@code null} if no
* analysis was possible.
* @param rootFailure the root failure passed to the analyzer
* @param cause the actual found cause
* @return the analysis or {@code null}
*/
protected abstract FailureAnalysis analyze(Throwable rootFailure, T cause);
/**
* Return the cause type being handled by the analyzer. By default the class generic
* is used.
* @return the cause type
*/
@SuppressWarnings("unchecked")
protected Class<? extends T> getCauseType() {
return (Class<? extends T>) ResolvableType
.forClass(AbstractFailureAnalyzer.class, getClass()).resolveGeneric();
}
@SuppressWarnings("unchecked")
protected final <E extends Throwable> E findCause(Throwable failure, Class<E> type) {
while (failure != null) {
if (type.isInstance(failure)) {
return (E) failure;
}
failure = failure.getCause();
}
return null;
}
}
AbstractFailureAnalyzer
是FailureAnalyzer
的基础实现抽象类,实现了FailureAnalyzer定义的analyze(Throwable failure)方法,并提供了一个指定异常类型的抽象方法analyze(Throwable rootFailure, T cause),
根据getCauseType()
方法获取当前类定义的第一个泛型类型,也就是我们需要分析的指定异常类型,根据异常类型返回异常的描述。
如何使用
public class TestFailureAnalyzer extends AbstractFailureAnalyzer<Exception> {
@Override
protected FailureAnalysis analyze(Throwable rootFailure, Exception cause) {
System.out.println(cause.getMessage());
return new FailureAnalysis(cause.getMessage(), "error", rootFailure);
}
}
SPI配置
创建如下文件: src/main/resources/META-INF/spring.factories才能生效
org.springframework.boot.diagnostics.FailureAnalyzer=com.start.TestFailureAnalyzer
这样我们就可以很清晰的看到了真实的错误:
Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'testController' method
public java.lang.String com.start.TestController.testInit1()
to { /initPool}: There is already 'testController' bean method
public java.lang.String com.start.TestController.testInit() mapped.