diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/CircularComponentScanException.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/CircularComponentScanException.java deleted file mode 100644 index f027dfff30..0000000000 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/CircularComponentScanException.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2002-2011 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.context.annotation; - -/** - * Exception thrown upon detection of circular {@link ComponentScan} use. - * - * @author Chris Beams - * @since 3.1 - */ -@SuppressWarnings("serial") -class CircularComponentScanException extends IllegalStateException { - - public CircularComponentScanException(String message, Exception cause) { - super(message, cause); - } - -} \ No newline at end of file diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java index d9abfacd5a..a06bd3d770 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.java @@ -326,7 +326,7 @@ public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateCo * new definition to be skipped in favor of the existing definition */ protected boolean isCompatible(BeanDefinition newDefinition, BeanDefinition existingDefinition) { - return (!(existingDefinition instanceof AnnotatedBeanDefinition) || // explicitly registered overriding bean + return (!(existingDefinition instanceof ScannedGenericBeanDefinition) || // explicitly registered overriding bean newDefinition.getSource().equals(existingDefinition.getSource()) || // scanned same file twice newDefinition.equals(existingDefinition)); // scanned equivalent class twice } diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java index e6f13861d4..585aa9efba 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java @@ -197,13 +197,7 @@ 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(), metadataReaderFactory)) { - try { - this.parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName()); - } catch (ConflictingBeanDefinitionException ex) { - throw new CircularComponentScanException( - "A conflicting bean definition was detected while processing @ComponentScan annotations. " + - "This usually indicates a circle between scanned packages.", ex); - } + this.parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName()); } } } diff --git a/org.springframework.context/src/test/java/org/springframework/context/annotation/ComponentScanAnnotationRecursionTests.java b/org.springframework.context/src/test/java/org/springframework/context/annotation/ComponentScanAnnotationRecursionTests.java index 7493b71905..82fc59e2e9 100644 --- a/org.springframework.context/src/test/java/org/springframework/context/annotation/ComponentScanAnnotationRecursionTests.java +++ b/org.springframework.context/src/test/java/org/springframework/context/annotation/ComponentScanAnnotationRecursionTests.java @@ -26,7 +26,7 @@ import org.springframework.context.annotation.componentscan.level2.Level2Config; import org.springframework.context.annotation.componentscan.level3.Level3Component; /** - * Tests ensuring that configuration clasess marked with @ComponentScan + * Tests ensuring that configuration classes marked with @ComponentScan * may be processed recursively * * @author Chris Beams @@ -50,11 +50,12 @@ public class ComponentScanAnnotationRecursionTests { assertThat(ctx.getBean("level2Bean"), sameInstance(ctx.getBean("level2Bean"))); } - @Test(expected=CircularComponentScanException.class) - public void cycleDetection() { + public void evenCircularScansAreSupported() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - ctx.register(LeftConfig.class); + ctx.register(LeftConfig.class); // left scans right, and right scans left ctx.refresh(); + ctx.getBean("leftConfig"); // but this is handled gracefully + ctx.getBean("rightConfig"); // and beans from both packages are available } } diff --git a/org.springframework.context/src/test/java/org/springframework/context/annotation/spr8808/Spr8808Tests.java b/org.springframework.context/src/test/java/org/springframework/context/annotation/spr8808/Spr8808Tests.java new file mode 100644 index 0000000000..7a765851f1 --- /dev/null +++ b/org.springframework.context/src/test/java/org/springframework/context/annotation/spr8808/Spr8808Tests.java @@ -0,0 +1,49 @@ +/* + * Copyright 2002-2011 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.context.annotation.spr8808; + +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +/** + * Tests cornering the bug in which @Configuration classes that @ComponentScan themselves + * would result in a ConflictingBeanDefinitionException. + * + * @author Chris Beams + * @since 3.1 + */ +public class Spr8808Tests { + + /** + * This test failed with ConflictingBeanDefinitionException prior to fixes for + * SPR-8808. + */ + @Test + public void repro() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(Config.class); + ctx.refresh(); + } + +} + +@Configuration +@ComponentScan(basePackageClasses=Spr8808Tests.class) // scan *this* package +class Config { +}