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 1ad3157481d..f2c6e0571dd 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 @@ -139,7 +139,7 @@ class ConfigurationClassParser { private final List propertySourceNames = new ArrayList<>(); - private final ImportStack importStack = new ImportStack(); + private ImportStack importStack = new ImportStack(); private List deferredImportSelectors; @@ -276,7 +276,16 @@ class ConfigurationClassParser { // Check the set of scanned definitions for any further config classes and parse recursively if necessary for (BeanDefinitionHolder holder : scannedBeanDefinitions) { if (ConfigurationClassUtils.checkConfigurationClassCandidate(holder.getBeanDefinition(), this.metadataReaderFactory)) { - parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName()); + // Provide isolated circular import detection for scanned classes, + // since the initial registration did not come explicitly. + ImportStack previousStack = this.importStack; + this.importStack = new ImportStack(); + try { + parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName()); + } + finally { + this.importStack = previousStack; + } } } } diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanAndImportAnnotationInteractionTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanAndImportAnnotationInteractionTests.java index 177e153e807..96b18066c16 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanAndImportAnnotationInteractionTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/ComponentScanAndImportAnnotationInteractionTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ package org.springframework.context.annotation; import org.junit.Test; import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.context.annotation.componentscan.importing.ImportingConfig; import org.springframework.context.annotation.componentscan.simple.SimpleComponent; /** @@ -58,7 +59,7 @@ public class ComponentScanAndImportAnnotationInteractionTests { @Test public void componentScanViaImportUsingAsm() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - ctx.registerBeanDefinition("config4", new RootBeanDefinition(Config3.class.getName())); + ctx.registerBeanDefinition("config", new RootBeanDefinition(Config3.class.getName())); ctx.refresh(); ctx.getBean(SimpleComponent.class); } @@ -71,6 +72,14 @@ public class ComponentScanAndImportAnnotationInteractionTests { ctx.getBean(SimpleComponent.class); } + @Test + public void circularImportViaComponentScan() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.registerBeanDefinition("config", new RootBeanDefinition(ImportingConfig.class.getName())); + ctx.refresh(); + ctx.getBean(SimpleComponent.class); + } + @ComponentScan("org.springframework.context.annotation.componentscan.simple") static final class Config1 { @@ -88,6 +97,7 @@ public class ComponentScanAndImportAnnotationInteractionTests { @ComponentScan("org.springframework.context.annotation.componentscan.simple") + @ComponentScan("org.springframework.context.annotation.componentscan.importing") public static final class ImportedConfig { }