diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java index 805923d2f1..fe9836f831 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java @@ -439,6 +439,7 @@ class ConfigurationClassParser { if (importCandidates.isEmpty()) { return; } + if (checkForCircularImports && this.importStack.contains(configClass)) { this.problemReporter.error(new CircularImportProblem(configClass, this.importStack, configClass.getMetadata())); } @@ -447,7 +448,7 @@ class ConfigurationClassParser { try { for (SourceClass candidate : importCandidates) { if (candidate.isAssignable(ImportSelector.class)) { - // the candidate class is an ImportSelector -> delegate to it to determine imports + // Candidate class is an ImportSelector -> delegate to it to determine imports Class candidateClass = candidate.loadClass(); ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class); invokeAwareMethods(selector); @@ -461,16 +462,18 @@ class ConfigurationClassParser { } } else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) { - // the candidate class is an ImportBeanDefinitionRegistrar -> delegate to it to register additional bean definitions + // Candidate class is an ImportBeanDefinitionRegistrar -> delegate to it to register additional bean definitions Class candidateClass = candidate.loadClass(); ImportBeanDefinitionRegistrar registrar = BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class); invokeAwareMethods(registrar); configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata()); } else { - // candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> process it as a @Configuration class - this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName()); - processConfigurationClass(candidate.asConfigClass(configClass)); + // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> process it as a @Configuration class + if (!this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { + this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName()); + processConfigurationClass(candidate.asConfigClass(configClass)); + } } } } diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ImportAwareTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ImportAwareTests.java index 77e2e88370..7212903777 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/ImportAwareTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/ImportAwareTests.java @@ -29,7 +29,9 @@ import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.core.type.AnnotationMetadata; +import org.springframework.core.type.StandardAnnotationMetadata; import org.springframework.scheduling.annotation.AsyncAnnotationBeanPostProcessor; import org.springframework.util.Assert; @@ -100,12 +102,31 @@ public class ImportAwareTests { assertNotNull(ctx.getBean(ImportedConfig.class)); } + @Test + public void metadataFromImportsOneThenTwo() { + AnnotationMetadata importMetadata = new AnnotationConfigApplicationContext( + ConfigurationOne.class, ConfigurationTwo.class) + .getBean(MetadataHolder.class).importMetadata; + assertEquals(ConfigurationOne.class, + ((StandardAnnotationMetadata) importMetadata).getIntrospectedClass()); + } + + @Test + public void metadataFromImportsTwoThenOne() { + AnnotationMetadata importMetadata = new AnnotationConfigApplicationContext( + ConfigurationTwo.class, ConfigurationOne.class) + .getBean(MetadataHolder.class).importMetadata; + assertEquals(ConfigurationOne.class, + ((StandardAnnotationMetadata) importMetadata).getIntrospectedClass()); + } + @Configuration @Import(ImportedConfig.class) static class ImportingConfig { } + @Configuration @EnableImportedConfig(foo="xyz") static class IndirectlyImportingConfig { @@ -152,7 +173,11 @@ public class ImportAwareTests { } - static class BPP implements BeanFactoryAware, BeanPostProcessor { + static class BPP implements BeanPostProcessor, BeanFactoryAware { + + @Override + public void setBeanFactory(BeanFactory beanFactory) { + } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) { @@ -163,10 +188,6 @@ public class ImportAwareTests { public Object postProcessAfterInitialization(Object bean, String beanName) { return bean; } - - @Override - public void setBeanFactory(BeanFactory beanFactory) { - } } @@ -206,4 +227,67 @@ public class ImportAwareTests { } } + + @EnableSomeConfiguration("bar") + @Configuration + public static class ConfigurationOne { + } + + + @Conditional(NeverMatchingCondition.class) + @EnableSomeConfiguration("foo") + @Configuration + public static class ConfigurationTwo { + } + + + @Import(SomeConfiguration.class) + @Target(ElementType.TYPE) + @Retention(RetentionPolicy.RUNTIME) + public @interface EnableSomeConfiguration { + + String value() default ""; + } + + + @Configuration + public static class SomeConfiguration implements ImportAware { + + private AnnotationMetadata importMetadata; + + @Override + public void setImportMetadata(AnnotationMetadata importMetadata) { + this.importMetadata = importMetadata; + } + + @Bean + public MetadataHolder holder() { + return new MetadataHolder(this.importMetadata); + } + } + + + public static class MetadataHolder { + + private final AnnotationMetadata importMetadata; + + public MetadataHolder(AnnotationMetadata importMetadata) { + this.importMetadata = importMetadata; + } + } + + + private static final class NeverMatchingCondition implements ConfigurationCondition { + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + return false; + } + + @Override + public ConfigurationPhase getConfigurationPhase() { + return ConfigurationPhase.REGISTER_BEAN; + } + } + }