Filter duplicates from SpringFactories loading

Filter duplicate class names when loading spring.factories files. The
prevents errors if -source jars are included on the classpath.

fixes gh-161
pull/176/head
Phillip Webb 11 years ago
parent 0d0de05ae6
commit 7c57541d50

@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanClassLoaderAware;
@ -53,10 +54,10 @@ class EnableAutoConfigurationImportSelector implements DeferredImportSelector,
.getAnnotationAttributes(EnableAutoConfiguration.class.getName(), .getAnnotationAttributes(EnableAutoConfiguration.class.getName(),
true)); true));
// Find all possible auto configuration classes // Find all possible auto configuration classes, filtering duplicates
List<String> factories = new ArrayList<String>( List<String> factories = new ArrayList<String>(new LinkedHashSet<String>(
SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class, SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,
this.beanClassLoader)); this.beanClassLoader)));
// Remove those specifically disabled // Remove those specifically disabled
factories.removeAll(Arrays.asList(attributes.getStringArray("exclude"))); factories.removeAll(Arrays.asList(attributes.getStringArray("exclude")));

@ -49,6 +49,7 @@ import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericApplicationContext; import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.GenericTypeResolver; import org.springframework.core.GenericTypeResolver;
import org.springframework.core.OrderComparator;
import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.env.CommandLinePropertySource; import org.springframework.core.env.CommandLinePropertySource;
import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.CompositePropertySource;
@ -232,11 +233,32 @@ public class SpringApplication {
* {@link SpringFactoriesLoader}. Subclasses can override this method to modify * {@link SpringFactoriesLoader}. Subclasses can override this method to modify
* default initializers if necessary. * default initializers if necessary.
*/ */
@SuppressWarnings({ "rawtypes", "unchecked" })
protected Collection<ApplicationContextInitializer<?>> getSpringFactoriesApplicationContextInitializers() { protected Collection<ApplicationContextInitializer<?>> getSpringFactoriesApplicationContextInitializers() {
return (Collection) SpringFactoriesLoader.loadFactories( ClassLoader classLoader = SpringApplication.class.getClassLoader();
ApplicationContextInitializer.class,
SpringApplication.class.getClassLoader()); // Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<String>(
SpringFactoriesLoader.loadFactoryNames(
ApplicationContextInitializer.class, classLoader));
List<ApplicationContextInitializer<?>> factories = new ArrayList<ApplicationContextInitializer<?>>(
names.size());
// Create instances from the names
for (String name : names) {
try {
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(ApplicationContextInitializer.class, instanceClass);
factories.add((ApplicationContextInitializer<?>) instanceClass
.newInstance());
}
catch (Throwable ex) {
throw new IllegalArgumentException(
"Cannot instantiate ApplicationContextInitializer : " + name, ex);
}
}
OrderComparator.sort(factories);
return factories;
} }
private Class<?> deduceMainApplicationClass() { private Class<?> deduceMainApplicationClass() {

Loading…
Cancel
Save