diff --git a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java index 1d63af9cb4b..d38392cdbe2 100644 --- a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -298,6 +298,7 @@ public class SpringApplication { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; + FailureAnalyzers analyzers = null; configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.started(); @@ -308,6 +309,7 @@ public class SpringApplication { applicationArguments); Banner printedBanner = printBanner(environment); context = createApplicationContext(); + analyzers = new FailureAnalyzers(context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); @@ -321,7 +323,7 @@ public class SpringApplication { return context; } catch (Throwable ex) { - handleRunFailure(context, listeners, ex); + handleRunFailure(context, listeners, analyzers, ex); throw new IllegalStateException(ex); } } @@ -803,14 +805,15 @@ public class SpringApplication { } private void handleRunFailure(ConfigurableApplicationContext context, - SpringApplicationRunListeners listeners, Throwable exception) { + SpringApplicationRunListeners listeners, FailureAnalyzers analyzers, + Throwable exception) { try { try { handleExitCode(context, exception); listeners.finished(context, exception); } finally { - reportFailure(exception, context); + reportFailure(analyzers, exception); if (context != null) { context.close(); } @@ -822,11 +825,9 @@ public class SpringApplication { ReflectionUtils.rethrowRuntimeException(exception); } - private void reportFailure(Throwable failure, - ConfigurableApplicationContext context) { + private void reportFailure(FailureAnalyzers analyzers, Throwable failure) { try { - if (FailureAnalyzers.analyzeAndReport(failure, getClass().getClassLoader(), - context)) { + if (analyzers != null && analyzers.analyzeAndReport(failure)) { registerLoggedException(failure); return; } diff --git a/spring-boot/src/main/java/org/springframework/boot/diagnostics/FailureAnalyzers.java b/spring-boot/src/main/java/org/springframework/boot/diagnostics/FailureAnalyzers.java index 1effcbdd44d..b6a2e1309b9 100644 --- a/spring-boot/src/main/java/org/springframework/boot/diagnostics/FailureAnalyzers.java +++ b/spring-boot/src/main/java/org/springframework/boot/diagnostics/FailureAnalyzers.java @@ -42,22 +42,50 @@ import org.springframework.util.ReflectionUtils; * * @author Andy Wilkinson * @author Phillip Webb + * @author Stephane Nicoll * @since 1.4.0 */ public final class FailureAnalyzers { private static final Log log = LogFactory.getLog(FailureAnalyzers.class); - private FailureAnalyzers() { + private final ClassLoader classLoader; + + private final List analyzers; + + public FailureAnalyzers(ConfigurableApplicationContext context) { + this.classLoader = context.getClassLoader(); + this.analyzers = loadFailureAnalyzers(this.classLoader); + prepareFailureAnalyzers(this.analyzers, context); + } + + /** + * Analyze and report the specified {@code failure}. + * + * @param failure the failure to analyze + * @return {@code true} if the failure was handled + */ + public boolean analyzeAndReport(Throwable failure) { + FailureAnalysis analysis = analyze(failure, this.analyzers); + return report(analysis, this.classLoader); } + /** + * Analyze and report the specified {@code failure}. + * + * @param failure the failure to analyze + * @param classLoader the classloader to use + * @param context the context to use + * @return {@code true} if the failure was handled + * @deprecated in favour of {@link #analyzeAndReport(Throwable)} + */ + @Deprecated public static boolean analyzeAndReport(Throwable failure, ClassLoader classLoader, ConfigurableApplicationContext context) { List analyzers = loadFailureAnalyzers(classLoader); - List reporters = SpringFactoriesLoader - .loadFactories(FailureAnalysisReporter.class, classLoader); - FailureAnalysis analysis = analyze(failure, analyzers, context); - return report(analysis, reporters); + prepareFailureAnalyzers(analyzers, context); + FailureAnalysis analysis = analyze(failure, analyzers); + return report(analysis, classLoader); } private static List loadFailureAnalyzers(ClassLoader classLoader) { @@ -79,10 +107,16 @@ public final class FailureAnalyzers { return analyzers; } - private static FailureAnalysis analyze(Throwable failure, - List analyzers, ConfigurableApplicationContext context) { + private static void prepareFailureAnalyzers(List analyzers, + ConfigurableApplicationContext context) { for (FailureAnalyzer analyzer : analyzers) { prepareAnalyzer(context, analyzer); + } + } + + private static FailureAnalysis analyze(Throwable failure, + List analyzers) { + for (FailureAnalyzer analyzer : analyzers) { FailureAnalysis analysis = analyzer.analyze(failure); if (analysis != null) { return analysis; @@ -99,7 +133,9 @@ public final class FailureAnalyzers { } private static boolean report(FailureAnalysis analysis, - List reporters) { + ClassLoader classLoader) { + List reporters = SpringFactoriesLoader + .loadFactories(FailureAnalysisReporter.class, classLoader); if (analysis == null || reporters.isEmpty()) { return false; } diff --git a/spring-boot/src/test/java/org/springframework/boot/diagnostics/FailureAnalyzersTests.java b/spring-boot/src/test/java/org/springframework/boot/diagnostics/FailureAnalyzersTests.java index 9a8137b0a3d..075c1cbe118 100644 --- a/spring-boot/src/test/java/org/springframework/boot/diagnostics/FailureAnalyzersTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/diagnostics/FailureAnalyzersTests.java @@ -70,8 +70,7 @@ public class FailureAnalyzersTests { private void analyzeAndReport(final String factoriesName, Throwable failure) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - - FailureAnalyzers.analyzeAndReport(failure, + context.setClassLoader( new ClassLoader(getClass().getClassLoader()) { @Override @@ -85,7 +84,8 @@ public class FailureAnalyzersTests { } } - }, context); + }); + new FailureAnalyzers(context).analyzeAndReport(failure); } static class BasicFailureAnalyzer implements FailureAnalyzer {