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
This commit is contained in:
Phillip Webb 2013-12-18 09:55:06 -08:00
parent 0d0de05ae6
commit 7c57541d50
2 changed files with 30 additions and 7 deletions

View File

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

View File

@ -49,6 +49,7 @@ import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.OrderComparator;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.env.CommandLinePropertySource;
import org.springframework.core.env.CompositePropertySource;
@ -232,11 +233,32 @@ public class SpringApplication {
* {@link SpringFactoriesLoader}. Subclasses can override this method to modify
* default initializers if necessary.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected Collection<ApplicationContextInitializer<?>> getSpringFactoriesApplicationContextInitializers() {
return (Collection) SpringFactoriesLoader.loadFactories(
ApplicationContextInitializer.class,
SpringApplication.class.getClassLoader());
ClassLoader classLoader = 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() {