Fix FailureAnalyzers tangle
Create a new `SpringBootExceptionReporter` interface so that a direct link between `SpringApplication` and `FailureAnalyzers` is no longer needed. This prevents package tangle warnings and allows for cleaner separation of concerns. Fixes gh-8612
This commit is contained in:
@@ -42,7 +42,6 @@ import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.boot.Banner.Mode;
|
||||
import org.springframework.boot.bind.PropertiesConfigurationFactory;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.boot.diagnostics.FailureAnalyzers;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
@@ -328,7 +327,7 @@ public class SpringApplication {
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
ConfigurableApplicationContext context = null;
|
||||
FailureAnalyzers analyzers = null;
|
||||
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
|
||||
configureHeadlessProperty();
|
||||
SpringApplicationRunListeners listeners = getRunListeners(args);
|
||||
listeners.starting();
|
||||
@@ -341,7 +340,8 @@ public class SpringApplication {
|
||||
bindToSpringApplication(environment);
|
||||
Banner printedBanner = printBanner(environment);
|
||||
context = createApplicationContext();
|
||||
analyzers = new FailureAnalyzers(context);
|
||||
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
|
||||
new Class[] { ConfigurableApplicationContext.class }, context);
|
||||
prepareContext(context, environment, listeners, applicationArguments,
|
||||
printedBanner);
|
||||
refreshContext(context);
|
||||
@@ -355,7 +355,7 @@ public class SpringApplication {
|
||||
return context;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
handleRunFailure(context, listeners, analyzers, ex);
|
||||
handleRunFailure(context, listeners, exceptionReporters, ex);
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
@@ -423,11 +423,11 @@ public class SpringApplication {
|
||||
SpringApplicationRunListener.class, types, this, args));
|
||||
}
|
||||
|
||||
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type) {
|
||||
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
|
||||
return getSpringFactoriesInstances(type, new Class<?>[] {});
|
||||
}
|
||||
|
||||
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
|
||||
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
|
||||
Class<?>[] parameterTypes, Object... args) {
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
// Use names and ensure unique to protect against duplicates
|
||||
@@ -853,15 +853,15 @@ public class SpringApplication {
|
||||
}
|
||||
|
||||
private void handleRunFailure(ConfigurableApplicationContext context,
|
||||
SpringApplicationRunListeners listeners, FailureAnalyzers analyzers,
|
||||
Throwable exception) {
|
||||
SpringApplicationRunListeners listeners,
|
||||
Collection<SpringBootExceptionReporter> exceptionReporters, Throwable exception) {
|
||||
try {
|
||||
try {
|
||||
handleExitCode(context, exception);
|
||||
listeners.finished(context, exception);
|
||||
}
|
||||
finally {
|
||||
reportFailure(analyzers, exception);
|
||||
reportFailure(exceptionReporters, exception);
|
||||
if (context != null) {
|
||||
context.close();
|
||||
}
|
||||
@@ -873,11 +873,14 @@ public class SpringApplication {
|
||||
ReflectionUtils.rethrowRuntimeException(exception);
|
||||
}
|
||||
|
||||
private void reportFailure(FailureAnalyzers analyzers, Throwable failure) {
|
||||
private void reportFailure(Collection<SpringBootExceptionReporter> exceptionReporters,
|
||||
Throwable failure) {
|
||||
try {
|
||||
if (analyzers != null && analyzers.analyzeAndReport(failure)) {
|
||||
registerLoggedException(failure);
|
||||
return;
|
||||
for (SpringBootExceptionReporter reporter : exceptionReporters) {
|
||||
if (reporter.reportException(failure)) {
|
||||
registerLoggedException(failure);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2012-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot;
|
||||
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
|
||||
/**
|
||||
* Callback interface used to support custom reporting of {@link SpringApplication}
|
||||
* startup errors. {@link SpringBootExceptionReporter reporters} are loaded via the
|
||||
* {@link SpringFactoriesLoader} and must declare a public constructor with a single
|
||||
* {@link ConfigurableApplicationContext} parameter.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 2.0.0
|
||||
* @see ApplicationContextAware
|
||||
*/
|
||||
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);
|
||||
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.boot.SpringBootExceptionReporter;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
@@ -44,9 +45,8 @@ import org.springframework.util.ReflectionUtils;
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public final class FailureAnalyzers {
|
||||
final class FailureAnalyzers implements SpringBootExceptionReporter {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(FailureAnalyzers.class);
|
||||
|
||||
@@ -54,12 +54,7 @@ public final class FailureAnalyzers {
|
||||
|
||||
private final List<FailureAnalyzer> analyzers;
|
||||
|
||||
/**
|
||||
* Create a new {@link FailureAnalyzers} instance.
|
||||
* @param context the source application context
|
||||
* @since 1.4.1
|
||||
*/
|
||||
public FailureAnalyzers(ConfigurableApplicationContext context) {
|
||||
FailureAnalyzers(ConfigurableApplicationContext context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
@@ -103,12 +98,8 @@ public final class FailureAnalyzers {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
@Override
|
||||
public boolean reportException(Throwable failure) {
|
||||
FailureAnalysis analysis = analyze(failure, this.analyzers);
|
||||
return report(analysis, this.classLoader);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@ org.springframework.boot.env.YamlPropertySourceLoader
|
||||
org.springframework.boot.SpringApplicationRunListener=\
|
||||
org.springframework.boot.context.event.EventPublishingRunListener
|
||||
|
||||
# Error Reporters
|
||||
org.springframework.boot.SpringBootExceptionReporter=\
|
||||
org.springframework.boot.diagnostics.FailureAnalyzers
|
||||
|
||||
# Application Context Initializers
|
||||
org.springframework.context.ApplicationContextInitializer=\
|
||||
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
|
||||
|
||||
@@ -78,7 +78,7 @@ public class FailureAnalyzersTests {
|
||||
private void analyzeAndReport(String factoriesName, Throwable failure) {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
ClassLoader classLoader = new CustomSpringFactoriesClassLoader(factoriesName);
|
||||
new FailureAnalyzers(context, classLoader).analyzeAndReport(failure);
|
||||
new FailureAnalyzers(context, classLoader).reportException(failure);
|
||||
}
|
||||
|
||||
static class BasicFailureAnalyzer implements FailureAnalyzer {
|
||||
|
||||
Reference in New Issue
Block a user