@Import detects and accepts existing configuration class in any order of processing

This commit is contained in:
Juergen Hoeller 2009-05-13 20:49:45 +00:00
parent 1ded650a6c
commit 14732c5dc2
4 changed files with 49 additions and 23 deletions

View File

@ -34,9 +34,7 @@ import org.springframework.util.ClassUtils;
/** /**
* Represents a user-defined {@link Configuration @Configuration} class. * Represents a user-defined {@link Configuration @Configuration} class.
* Includes a set of {@link Bean} methods, including all such methods defined in the * 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} * ancestry of the class, in a 'flattened-out' manner.
* representation contains source information about where it was originally detected
* (for the purpose of tooling with Spring IDE).
* *
* @author Chris Beams * @author Chris Beams
* @author Juergen Hoeller * @author Juergen Hoeller
@ -131,14 +129,8 @@ final class ConfigurationClass {
@Override @Override
public boolean equals(Object other) { public boolean equals(Object other) {
if (this == other) { return (this == other || (other instanceof ConfigurationClass &&
return true; getMetadata().getClassName().equals(((ConfigurationClass) other).getMetadata().getClassName())));
}
if (!(other instanceof ConfigurationClass)) {
return false;
}
ConfigurationClass otherCc = (ConfigurationClass) other;
return getMetadata().getClassName().equals(otherCc.getMetadata().getClassName());
} }
@Override @Override

View File

@ -51,6 +51,7 @@ import org.springframework.util.StringUtils;
* @author Chris Beams * @author Chris Beams
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 3.0 * @since 3.0
* @see ConfigurationClassParser
*/ */
class ConfigurationClassBeanDefinitionReader { class ConfigurationClassBeanDefinitionReader {

View File

@ -37,12 +37,12 @@ import org.springframework.core.type.classreading.MetadataReaderFactory;
/** /**
* Parses a {@link Configuration} class definition, populating a configuration model. * Parses a {@link Configuration} class definition, populating a configuration model.
* This ASM-based implementation avoids reflection and eager classloading in order to * This ASM-based implementation avoids reflection and eager class loading in order to
* interoperate effectively with tooling (Spring IDE) and OSGi environments. * interoperate effectively with lazy class loading in a Spring ApplicationContext.
* *
* <p>This class helps separate the concern of parsing the structure of a Configuration class * <p>This class helps separate the concern of parsing the structure of a Configuration
* from the concern of registering {@link BeanDefinition} objects based on the content of * class from the concern of registering {@link BeanDefinition} objects based on the
* that model. * content of that model.
* *
* @author Chris Beams * @author Chris Beams
* @author Juergen Hoeller * @author Juergen Hoeller
@ -112,7 +112,12 @@ class ConfigurationClassParser {
metadata = null; 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 { protected void doProcessConfigurationClass(ConfigurationClass configClass, AnnotationMetadata metadata) throws IOException {

View File

@ -18,8 +18,10 @@ package org.springframework.context.annotation.configuration;
import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import org.junit.Test; import org.junit.Test;
import test.beans.ITestBean;
import test.beans.TestBean;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition; 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.ConfigurationClassPostProcessor;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import test.beans.ITestBean;
import test.beans.TestBean;
/** /**
* System tests for {@link Import} annotation support. * System tests for {@link Import} annotation support.
@ -58,10 +57,30 @@ public class ImportTests {
public void testProcessImports() { public void testProcessImports() {
int configClasses = 2; int configClasses = 2;
int beansInClasses = 2; int beansInClasses = 2;
assertBeanDefinitionCount((configClasses + beansInClasses), ConfigurationWithImportAnnotation.class); 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 @Configuration
@Import(OtherConfiguration.class) @Import(OtherConfiguration.class)
static class ConfigurationWithImportAnnotation { static class ConfigurationWithImportAnnotation {
@ -72,13 +91,22 @@ public class ImportTests {
} }
@Configuration @Configuration
static class OtherConfiguration { @Import(OtherConfiguration.class)
static class OtherConfigurationWithImportAnnotation {
@Bean @Bean
public ITestBean two() { public ITestBean two() {
return new TestBean(); return new TestBean();
} }
} }
@Configuration
static class OtherConfiguration {
@Bean
public ITestBean three() {
return new TestBean();
}
}
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@Test @Test