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 0d5221d58fb..bf188510d9f 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 @@ -66,6 +66,7 @@ import org.springframework.core.type.StandardAnnotationMetadata; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.AssignableTypeFilter; +import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; @@ -315,9 +316,7 @@ class ConfigurationClassParser { String name = propertySource.getString("name"); String[] locations = propertySource.getStringArray("value"); boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound"); - if (locations.length == 0) { - throw new IllegalArgumentException("At least one @PropertySource(value) location is required"); - } + Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required"); for (String location : locations) { try { String resolvedLocation = this.environment.resolveRequiredPlaceholders(location); @@ -401,6 +400,7 @@ class ConfigurationClassParser { if (importCandidates.isEmpty()) { return; } + if (checkForCircularImports && this.importStack.contains(configClass)) { this.problemReporter.error(new CircularImportProblem(configClass, this.importStack, configClass.getMetadata())); } @@ -409,12 +409,13 @@ 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); if (selector instanceof DeferredImportSelector) { - this.deferredImportSelectors.add(new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector)); + this.deferredImportSelectors.add( + new DeferredImportSelectorHolder(configClass, (DeferredImportSelector) selector)); } else { String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata()); @@ -423,15 +424,19 @@ 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); + 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()); + // 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)); } } @@ -645,12 +650,12 @@ class ConfigurationClassParser { /** - * Simple wrapper that allows annotated source classes to be dealt with in a uniform - * manor, regardless of how they are loaded. + * Simple wrapper that allows annotated source classes to be dealt with + * in a uniform manner, regardless of how they are loaded. */ private class SourceClass { - private final Object source; // Class or MetaDataReader + private final Object source; // Class or MetadataReader private final AnnotationMetadata metadata; diff --git a/spring-context/src/test/java/org/springframework/context/annotation/spr12334/Spr12334Tests.java b/spring-context/src/test/java/org/springframework/context/annotation/spr12334/Spr12334Tests.java index 56e7a3d8b27..c98fc077382 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/spr12334/Spr12334Tests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/spr12334/Spr12334Tests.java @@ -33,6 +33,8 @@ public class Spr12334Tests { @Test public void shouldNotScanTwice() { + TestImport.scanned = false; + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.scan(TestImport.class.getPackage().getName()); context.refresh(); @@ -53,14 +55,14 @@ public class Spr12334Tests { public static class TestImport implements ImportBeanDefinitionRegistrar { - private boolean scanned = false; + private static boolean scanned = false; @Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { - if (this.scanned) { + if (scanned) { throw new IllegalStateException("Already scanned"); } - this.scanned = true; + scanned = true; } }