From f67c8bcfd80ac634d3dc97c26198ec81682f4cdd Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 13 May 2009 20:49:45 +0000 Subject: [PATCH] @Import detects and accepts existing configuration class in any order of processing git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@1176 50f2f4bb-b051-0410-bef5-90022cba6387 --- .../annotation/ConfigurationClass.java | 14 ++----- ...onfigurationClassBeanDefinitionReader.java | 1 + .../annotation/ConfigurationClassParser.java | 17 +++++--- .../annotation/configuration/ImportTests.java | 40 ++++++++++++++++--- 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java index e9065a526ae..a577f1028d8 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClass.java @@ -34,9 +34,7 @@ import org.springframework.util.ClassUtils; /** * Represents a user-defined {@link Configuration @Configuration} class. * Includes a set of {@link Bean} methods, including all such methods defined in the - * ancestry of the class, in a 'flattened-out' manner. Note that each {@link ConfigurationClassMethod} - * representation contains source information about where it was originally detected - * (for the purpose of tooling with Spring IDE). + * ancestry of the class, in a 'flattened-out' manner. * * @author Chris Beams * @author Juergen Hoeller @@ -131,14 +129,8 @@ final class ConfigurationClass { @Override public boolean equals(Object other) { - if (this == other) { - return true; - } - if (!(other instanceof ConfigurationClass)) { - return false; - } - ConfigurationClass otherCc = (ConfigurationClass) other; - return getMetadata().getClassName().equals(otherCc.getMetadata().getClassName()); + return (this == other || (other instanceof ConfigurationClass && + getMetadata().getClassName().equals(((ConfigurationClass) other).getMetadata().getClassName()))); } @Override diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java index 0637a1351e1..0b7af9b1d25 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java @@ -51,6 +51,7 @@ import org.springframework.util.StringUtils; * @author Chris Beams * @author Juergen Hoeller * @since 3.0 + * @see ConfigurationClassParser */ class ConfigurationClassBeanDefinitionReader { 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 64482a637f0..87f2f412789 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 @@ -37,12 +37,12 @@ import org.springframework.core.type.classreading.MetadataReaderFactory; /** * Parses a {@link Configuration} class definition, populating a configuration model. - * This ASM-based implementation avoids reflection and eager classloading in order to - * interoperate effectively with tooling (Spring IDE) and OSGi environments. + * This ASM-based implementation avoids reflection and eager class loading in order to + * interoperate effectively with lazy class loading in a Spring ApplicationContext. * - *

This class helps separate the concern of parsing the structure of a Configuration class - * from the concern of registering {@link BeanDefinition} objects based on the content of - * that model. + *

This class helps separate the concern of parsing the structure of a Configuration + * class from the concern of registering {@link BeanDefinition} objects based on the + * content of that model. * * @author Chris Beams * @author Juergen Hoeller @@ -112,7 +112,12 @@ class ConfigurationClassParser { metadata = null; } } - model.add(configClass); + if (this.model.contains(configClass) && configClass.getBeanName() != null) { + // Explicit bean definition found, probably replacing an import. + // Let's remove the old one and go with the new one. + this.model.remove(configClass); + } + this.model.add(configClass); } protected void doProcessConfigurationClass(ConfigurationClass configClass, AnnotationMetadata metadata) throws IOException { diff --git a/org.springframework.context/src/test/java/org/springframework/context/annotation/configuration/ImportTests.java b/org.springframework.context/src/test/java/org/springframework/context/annotation/configuration/ImportTests.java index 01e4bf859ad..c2115e960dd 100644 --- a/org.springframework.context/src/test/java/org/springframework/context/annotation/configuration/ImportTests.java +++ b/org.springframework.context/src/test/java/org/springframework/context/annotation/configuration/ImportTests.java @@ -18,8 +18,10 @@ package org.springframework.context.annotation.configuration; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; - import org.junit.Test; +import test.beans.ITestBean; +import test.beans.TestBean; + import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; @@ -28,9 +30,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ConfigurationClassPostProcessor; import org.springframework.context.annotation.Import; -import test.beans.ITestBean; -import test.beans.TestBean; - /** * System tests for {@link Import} annotation support. @@ -58,10 +57,30 @@ public class ImportTests { public void testProcessImports() { int configClasses = 2; int beansInClasses = 2; - assertBeanDefinitionCount((configClasses + beansInClasses), ConfigurationWithImportAnnotation.class); } + @Test + public void testProcessImportsWithDoubleImports() { + int configClasses = 3; + int beansInClasses = 3; + assertBeanDefinitionCount((configClasses + beansInClasses), ConfigurationWithImportAnnotation.class, OtherConfigurationWithImportAnnotation.class); + } + + @Test + public void testProcessImportsWithExplicitOverridingBefore() { + int configClasses = 2; + int beansInClasses = 2; + assertBeanDefinitionCount((configClasses + beansInClasses), OtherConfiguration.class, ConfigurationWithImportAnnotation.class); + } + + @Test + public void testProcessImportsWithExplicitOverridingAfter() { + int configClasses = 2; + int beansInClasses = 2; + assertBeanDefinitionCount((configClasses + beansInClasses), ConfigurationWithImportAnnotation.class, OtherConfiguration.class); + } + @Configuration @Import(OtherConfiguration.class) static class ConfigurationWithImportAnnotation { @@ -72,13 +91,22 @@ public class ImportTests { } @Configuration - static class OtherConfiguration { + @Import(OtherConfiguration.class) + static class OtherConfigurationWithImportAnnotation { @Bean public ITestBean two() { return new TestBean(); } } + @Configuration + static class OtherConfiguration { + @Bean + public ITestBean three() { + return new TestBean(); + } + } + // ------------------------------------------------------------------------ @Test