diff --git a/spring-context/src/main/java/org/springframework/context/annotation/AnnotatedBeanDefinitionReader.java b/spring-context/src/main/java/org/springframework/context/annotation/AnnotatedBeanDefinitionReader.java index 59aae4630b8..be17b59d6d5 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/AnnotatedBeanDefinitionReader.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/AnnotatedBeanDefinitionReader.java @@ -134,10 +134,10 @@ public class AnnotatedBeanDefinitionReader { } public void registerBean(Class annotatedClass, String name, Class... qualifiers) { - if (shouldSkip(annotatedClass)) { + AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass); + if (conditionEvaluator.shouldSkip(abd.getMetadata())) { return; } - AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass); ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry)); @@ -161,17 +161,6 @@ public class AnnotatedBeanDefinitionReader { } - private boolean shouldSkip(Class annotatedClass) { - while(annotatedClass != null) { - AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass); - if(conditionEvaluator.shouldSkip(abd.getMetadata())) { - return true; - } - annotatedClass = annotatedClass.getSuperclass(); - } - return false; - } - /** * Get the Environment from the given registry if possible, otherwise return a new * StandardEnvironment. diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java b/spring-context/src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java index 45ad9101111..08336b34b03 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ClassPathScanningCandidateComponentProvider.java @@ -38,7 +38,6 @@ import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternUtils; -import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.classreading.CachingMetadataReaderFactory; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; @@ -342,29 +341,24 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC } for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, this.metadataReaderFactory)) { - return !shouldSkip(metadataReader); + return isConditionMatch(metadataReader); } } return false; } - private boolean shouldSkip(MetadataReader metadataReader) throws IOException { + /** + * Determine whether the given class is a candidate component based on any + * {@code @Conditional} annotations. + * @param metadataReader the ASM ClassReader for the class + * @return whether the class qualifies as a candidate component + */ + private boolean isConditionMatch(MetadataReader metadataReader) { if (this.conditionEvaluator == null) { this.conditionEvaluator = new ConditionEvaluator(getRegistry(), getEnvironment(), null, null, getResourceLoader()); } - - while(metadataReader != null) { - AnnotationMetadata metadata = metadataReader.getAnnotationMetadata(); - if(this.conditionEvaluator.shouldSkip(metadata)) { - return true; - } - metadataReader = (metadata.hasSuperClass() ? - this.metadataReaderFactory.getMetadataReader(metadata.getSuperClassName()) - : null); - } - - return false; + return !conditionEvaluator.shouldSkip(metadataReader.getAnnotationMetadata()); } /** diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConditionEvaluator.java b/spring-context/src/main/java/org/springframework/context/annotation/ConditionEvaluator.java index ea93744f138..7903bca448d 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConditionEvaluator.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConditionEvaluator.java @@ -50,6 +50,7 @@ class ConditionEvaluator { */ public ConditionEvaluator(BeanDefinitionRegistry registry, Environment environment, ApplicationContext applicationContext, ClassLoader classLoader, ResourceLoader resourceLoader) { + this.context = new ConditionContextImpl(registry, environment, applicationContext, classLoader, resourceLoader); } @@ -72,6 +73,10 @@ class ConditionEvaluator { * @return if the item should be skipped */ public boolean shouldSkip(AnnotatedTypeMetadata metadata, ConfigurationPhase phase) { + if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) { + return false; + } + if (phase == null) { if (metadata instanceof AnnotationMetadata && ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) { @@ -94,7 +99,6 @@ class ConditionEvaluator { } } } - return false; } diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java index 1afb06bf1f5..38f6aaac2ba 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java @@ -16,12 +16,10 @@ package org.springframework.context.annotation; -import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; -import java.util.List; import java.util.Map; import java.util.Set; @@ -53,8 +51,6 @@ final class ConfigurationClass { private final AnnotationMetadata metadata; - private final List metadataHierarchy = new ArrayList(); - private final Resource resource; private String beanName; @@ -133,14 +129,6 @@ final class ConfigurationClass { return this.metadata; } - public List getMetadataHierarchy() { - return Collections.unmodifiableList(metadataHierarchy); - } - - public void addMetadataHierarchy(AnnotationMetadata metadata) { - this.metadataHierarchy.add(metadata); - } - public Resource getResource() { return this.resource; } diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java index 4ef9ba19c8a..291c68cbc0d 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java @@ -380,22 +380,13 @@ class ConfigurationClassBeanDefinitionReader { } } if (skip == null) { - skip = shouldSkipConsideringHierarchy(configClass); + skip = conditionEvaluator.shouldSkip(configClass.getMetadata(), + ConfigurationPhase.REGISTER_BEAN); } this.skipped.put(configClass, skip); } return skip; } - - private boolean shouldSkipConsideringHierarchy(ConfigurationClass configClass) { - for (AnnotationMetadata metadata : configClass.getMetadataHierarchy()) { - if (conditionEvaluator.shouldSkip(metadata, - ConfigurationPhase.REGISTER_BEAN)) { - return true; - } - } - return false; - } } } 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 95dc6d14b9f..f2550993bfb 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 @@ -183,7 +183,7 @@ class ConfigurationClassParser { protected void processConfigurationClass(ConfigurationClass configClass) throws IOException { - if (shouldSkip(asSourceClass(configClass), ConfigurationPhase.PARSE_CONFIGURATION)) { + if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) { return; } @@ -201,7 +201,6 @@ class ConfigurationClassParser { // Recursively process the configuration class and its superclass hierarchy. SourceClass sourceClass = asSourceClass(configClass); do { - configClass.addMetadataHierarchy(sourceClass.getMetadata()); sourceClass = doProcessConfigurationClass(configClass, sourceClass); } while (sourceClass != null); @@ -231,7 +230,7 @@ class ConfigurationClassParser { AnnotationAttributes componentScan = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ComponentScan.class); if (componentScan != null) { // the config class is annotated with @ComponentScan -> perform the scan immediately - if (!shouldSkip(sourceClass, ConfigurationPhase.REGISTER_BEAN)) { + if (!conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { Set scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); @@ -270,7 +269,12 @@ class ConfigurationClassParser { if (!this.knownSuperclasses.containsKey(superclass)) { this.knownSuperclasses.put(superclass, configClass); // superclass found, return its annotation metadata and recurse - return sourceClass.getSuperClass(); + try { + return sourceClass.getSuperClass(); + } + catch (ClassNotFoundException ex) { + throw new IllegalStateException(ex); + } } } @@ -278,17 +282,6 @@ class ConfigurationClassParser { return null; } - private boolean shouldSkip(SourceClass sourceClass, ConfigurationPhase phase) - throws IOException { - while (sourceClass != null) { - if (conditionEvaluator.shouldSkip(sourceClass.getMetadata(), phase)) { - return true; - } - sourceClass = sourceClass.getSuperClass(); - } - return false; - } - /** * Register member (nested) classes that happen to be configuration classes themselves. * @param sourceClass the source class to process @@ -699,19 +692,11 @@ class ConfigurationClassParser { return members; } - public SourceClass getSuperClass() throws IOException { - if (!getMetadata().hasSuperClass()) { - return null; - } - try { - if (this.source instanceof Class) { - return asSourceClass(((Class) this.source).getSuperclass()); - } - return asSourceClass(((MetadataReader) this.source).getClassMetadata().getSuperClassName()); - } - catch (ClassNotFoundException ex) { - throw new IllegalStateException(ex); + public SourceClass getSuperClass() throws IOException, ClassNotFoundException { + if (this.source instanceof Class) { + return asSourceClass(((Class) this.source).getSuperclass()); } + return asSourceClass(((MetadataReader) this.source).getClassMetadata().getSuperClassName()); } public Set getAnnotations() throws IOException, ClassNotFoundException { diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassWithConditionTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassWithConditionTests.java index eb33841a93b..d26e6b5f785 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassWithConditionTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassWithConditionTests.java @@ -54,21 +54,6 @@ public class ConfigurationClassWithConditionTests { ctx.close(); } - @Test - public void conditionalOnConfiguration() throws Exception { - ctx.register(ConditionOnConfiguration.class); - ctx.refresh(); - assertThat(ctx.getBeansOfType(ConditionOnConfiguration.class).size(), equalTo(0)); - } - - @Test - public void inheritedConditionalOnConfiguration() throws Exception { - ctx.register(InheritedConditionOnConfiguration.class); - ctx.refresh(); - assertThat(ctx.getBeansOfType(ConditionOnConfiguration.class).size(), equalTo(0)); - assertThat(ctx.getBeansOfType(InheritedConditionOnConfiguration.class).size(), equalTo(0)); - } - @Test public void conditionalOnMissingBeanMatch() throws Exception { ctx.register(BeanOneConfiguration.class, BeanTwoConfiguration.class); @@ -118,14 +103,6 @@ public class ConfigurationClassWithConditionTests { assertNull(ctx.getBean(NonConfigurationClass.class)); } - @Test - public void inheritedNonConfigurationClass() throws Exception { - ctx.register(InheritedNonConfigurationClass.class); - ctx.refresh(); - thrown.expect(NoSuchBeanDefinitionException.class); - assertNull(ctx.getBean(InheritedNonConfigurationClass.class)); - } - @Test public void methodConditional() throws Exception { ctx.register(ConditionOnMethodConfiguration.class); @@ -141,13 +118,6 @@ public class ConfigurationClassWithConditionTests { ctx.refresh(); } - @Test - public void inheritedImportsNotCreated() throws Exception { - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - ctx.register(InheritedImportsNotCreated.class); - ctx.refresh(); - } - @Test public void importsNotLoaded() throws Exception { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); @@ -258,10 +228,6 @@ public class ConfigurationClassWithConditionTests { static class NonConfigurationClass { } - @Component - static class InheritedNonConfigurationClass extends NonConfigurationClass { - } - @Configuration static class ConditionOnMethodConfiguration { @@ -281,21 +247,6 @@ public class ConfigurationClassWithConditionTests { } } - @Configuration - @Never - static class ConditionOnConfiguration { - } - - @Configuration - static class InheritedConditionOnConfiguration extends ConditionOnConfiguration { - } - - - @Import({ ConfigurationNotCreated.class, RegistrarNotCreated.class, ImportSelectorNotCreated.class }) - static class InheritedImportsNotCreated extends ConditionOnConfiguration { - - } - @Configuration static class ConfigurationNotCreated { static {