|
|
|
|
@@ -25,6 +25,8 @@ import java.util.Comparator;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.Iterator;
|
|
|
|
|
import java.util.LinkedHashSet;
|
|
|
|
|
import java.util.LinkedList;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Set;
|
|
|
|
|
import java.util.Stack;
|
|
|
|
|
@@ -32,19 +34,23 @@ import java.util.Stack;
|
|
|
|
|
import org.springframework.beans.BeanUtils;
|
|
|
|
|
import org.springframework.beans.factory.Aware;
|
|
|
|
|
import org.springframework.beans.factory.BeanClassLoaderAware;
|
|
|
|
|
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
|
|
|
|
import org.springframework.beans.factory.BeanFactory;
|
|
|
|
|
import org.springframework.beans.factory.BeanFactoryAware;
|
|
|
|
|
import org.springframework.beans.factory.config.BeanDefinition;
|
|
|
|
|
import org.springframework.beans.factory.config.BeanDefinitionHolder;
|
|
|
|
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
|
|
|
|
import org.springframework.beans.factory.parsing.Location;
|
|
|
|
|
import org.springframework.beans.factory.parsing.Problem;
|
|
|
|
|
import org.springframework.beans.factory.parsing.ProblemReporter;
|
|
|
|
|
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
|
|
|
|
import org.springframework.beans.factory.support.BeanDefinitionReader;
|
|
|
|
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
|
|
|
|
import org.springframework.beans.factory.support.BeanNameGenerator;
|
|
|
|
|
import org.springframework.context.ResourceLoaderAware;
|
|
|
|
|
import org.springframework.core.NestedIOException;
|
|
|
|
|
import org.springframework.core.annotation.AnnotationAttributes;
|
|
|
|
|
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
|
|
|
|
import org.springframework.core.env.CompositePropertySource;
|
|
|
|
|
import org.springframework.core.env.Environment;
|
|
|
|
|
import org.springframework.core.env.PropertySource;
|
|
|
|
|
@@ -82,6 +88,15 @@ import static org.springframework.context.annotation.MetadataUtils.*;
|
|
|
|
|
*/
|
|
|
|
|
class ConfigurationClassParser {
|
|
|
|
|
|
|
|
|
|
private static final Comparator<DeferredImportSelectorHolder> DEFERRED_IMPORT_COMPARATOR =
|
|
|
|
|
new Comparator<ConfigurationClassParser.DeferredImportSelectorHolder>() {
|
|
|
|
|
public int compare(DeferredImportSelectorHolder o1,
|
|
|
|
|
DeferredImportSelectorHolder o2) {
|
|
|
|
|
return AnnotationAwareOrderComparator.INSTANCE.compare(
|
|
|
|
|
o1.getImportSelector(), o2.getImportSelector());
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private final MetadataReaderFactory metadataReaderFactory;
|
|
|
|
|
|
|
|
|
|
private final ProblemReporter problemReporter;
|
|
|
|
|
@@ -106,6 +121,8 @@ class ConfigurationClassParser {
|
|
|
|
|
|
|
|
|
|
private final BeanNameGenerator beanNameGenerator;
|
|
|
|
|
|
|
|
|
|
private final List<DeferredImportSelectorHolder> deferredImportSelectors =
|
|
|
|
|
new LinkedList<DeferredImportSelectorHolder>();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create a new {@link ConfigurationClassParser} instance that will be used
|
|
|
|
|
@@ -125,6 +142,23 @@ class ConfigurationClassParser {
|
|
|
|
|
resourceLoader, environment, componentScanBeanNameGenerator, registry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void parse(Set<BeanDefinitionHolder> configCandidates) {
|
|
|
|
|
for (BeanDefinitionHolder holder : configCandidates) {
|
|
|
|
|
BeanDefinition bd = holder.getBeanDefinition();
|
|
|
|
|
try {
|
|
|
|
|
if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
|
|
|
|
|
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
parse(bd.getBeanClassName(), holder.getBeanName());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (IOException ex) {
|
|
|
|
|
throw new BeanDefinitionStoreException("Failed to load bean class: " + bd.getBeanClassName(), ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
processDeferredImportSelectors();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parse the specified {@link Configuration @Configuration} class.
|
|
|
|
|
@@ -142,7 +176,7 @@ class ConfigurationClassParser {
|
|
|
|
|
* @param clazz the Class to parse
|
|
|
|
|
* @param beanName must not be null (as of Spring 3.1.1)
|
|
|
|
|
*/
|
|
|
|
|
public void parse(Class<?> clazz, String beanName) throws IOException {
|
|
|
|
|
protected void parse(Class<?> clazz, String beanName) throws IOException {
|
|
|
|
|
processConfigurationClass(new ConfigurationClass(clazz, beanName));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -369,6 +403,21 @@ class ConfigurationClassParser {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void processDeferredImportSelectors() {
|
|
|
|
|
Collections.sort(this.deferredImportSelectors, DEFERRED_IMPORT_COMPARATOR);
|
|
|
|
|
for (DeferredImportSelectorHolder deferredImport : this.deferredImportSelectors) {
|
|
|
|
|
try {
|
|
|
|
|
ConfigurationClass configClass = deferredImport.getConfigurationClass();
|
|
|
|
|
String[] imports = deferredImport.getImportSelector().selectImports(configClass.getMetadata());
|
|
|
|
|
processImport(configClass, Arrays.asList(imports), false);
|
|
|
|
|
}
|
|
|
|
|
catch (IOException ex) {
|
|
|
|
|
throw new BeanDefinitionStoreException("Failed to load bean class: ", ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
deferredImportSelectors.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void processImport(ConfigurationClass configClass, Collection<?> classesToImport, boolean checkForCircularImports) throws IOException {
|
|
|
|
|
if (checkForCircularImports && this.importStack.contains(configClass)) {
|
|
|
|
|
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack, configClass.getMetadata()));
|
|
|
|
|
@@ -384,7 +433,12 @@ class ConfigurationClassParser {
|
|
|
|
|
Class<?> candidateClass = (candidate instanceof Class ? (Class) candidate : this.resourceLoader.getClassLoader().loadClass((String) candidate));
|
|
|
|
|
ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);
|
|
|
|
|
invokeAwareMethods(selector);
|
|
|
|
|
processImport(configClass, Arrays.asList(selector.selectImports(importingClassMetadata)), false);
|
|
|
|
|
if(selector instanceof DeferredImportSelector) {
|
|
|
|
|
this.deferredImportSelectors.add(new DeferredImportSelectorHolder(
|
|
|
|
|
configClass, (DeferredImportSelector) selector));
|
|
|
|
|
} else {
|
|
|
|
|
processImport(configClass, Arrays.asList(selector.selectImports(importingClassMetadata)), false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (checkAssignability(ImportBeanDefinitionRegistrar.class, candidateToCheck)) {
|
|
|
|
|
// the candidate class is an ImportBeanDefinitionRegistrar -> delegate to it to register additional bean definitions
|
|
|
|
|
@@ -539,4 +593,24 @@ class ConfigurationClassParser {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static class DeferredImportSelectorHolder {
|
|
|
|
|
|
|
|
|
|
private ConfigurationClass configurationClass;
|
|
|
|
|
|
|
|
|
|
private DeferredImportSelector importSelector;
|
|
|
|
|
|
|
|
|
|
public DeferredImportSelectorHolder(ConfigurationClass configurationClass, DeferredImportSelector importSelector) {
|
|
|
|
|
this.configurationClass = configurationClass;
|
|
|
|
|
this.importSelector = importSelector;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ConfigurationClass getConfigurationClass() {
|
|
|
|
|
return configurationClass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public DeferredImportSelector getImportSelector() {
|
|
|
|
|
return importSelector;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|