diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java index 914b9d9ce79..d147a506561 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -109,6 +109,8 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) { this.reader.setBeanNameGenerator(beanNameGenerator); this.scanner.setBeanNameGenerator(beanNameGenerator); + this.getBeanFactory().registerSingleton( + AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator); } /** diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java index 72592b9cf42..793ba314b4b 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java @@ -56,6 +56,17 @@ public class AnnotationConfigUtils { public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"; + /** + * The bean name of the internally managed BeanNameGenerator for use when processing + * {@link Configuration} classes. Set by {@link AnnotationConfigApplicationContext} + * and {@code AnnotationConfigWebApplicationContext} during bootstrap in order to make + * any custom name generation strategy available to the underlying + * {@link ConfigurationClassPostProcessor}. + * @since 3.1.1 + */ + public static final String CONFIGURATION_BEAN_NAME_GENERATOR = + "org.springframework.context.annotation.internalConfigurationBeanNameGenerator"; + /** * The bean name of the internally managed Autowired annotation processor. */ @@ -249,4 +260,5 @@ public class AnnotationConfigUtils { return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass); } + } diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ComponentScan.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ComponentScan.java index 20729b0c5b3..f0826a62ebe 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ComponentScan.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ComponentScan.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2012 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. @@ -77,8 +77,14 @@ public @interface ComponentScan { /** * The {@link BeanNameGenerator} class to be used for naming detected components * within the Spring container. + *
The default value of the {@link BeanNameGenerator} interface itself indicates + * that the scanner used to process this {@code @ComponentScan} annotation should + * use its inherited bean name generator, e.g. the default + * {@link AnnotationBeanNameGenerator} or any custom instance supplied to the + * application context at bootstrap time. + * @see AnnotationConfigApplicationContext#setBeanNameGenerator(BeanNameGenerator) */ - Class extends BeanNameGenerator> nameGenerator() default AnnotationBeanNameGenerator.class; + Class extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class; /** * The {@link ScopeMetadataResolver} to be used for resolving the scope of detected components. diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ComponentScanAnnotationParser.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ComponentScanAnnotationParser.java index 9fa82e40c78..a549b8d0af3 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ComponentScanAnnotationParser.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ComponentScanAnnotationParser.java @@ -51,11 +51,16 @@ class ComponentScanAnnotationParser { private final BeanDefinitionRegistry registry; + private final BeanNameGenerator beanNameGenerator; + public ComponentScanAnnotationParser( - ResourceLoader resourceLoader, Environment environment, BeanDefinitionRegistry registry) { + ResourceLoader resourceLoader, Environment environment, + BeanNameGenerator beanNameGenerator, BeanDefinitionRegistry registry) { + this.resourceLoader = resourceLoader; this.environment = environment; + this.beanNameGenerator = beanNameGenerator; this.registry = registry; } @@ -71,7 +76,10 @@ class ComponentScanAnnotationParser { scanner.setResourceLoader(this.resourceLoader); Class extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator"); - scanner.setBeanNameGenerator(BeanUtils.instantiateClass(generatorClass)); + boolean useInheritedGenerator = BeanNameGenerator.class.equals(generatorClass); + scanner.setBeanNameGenerator(useInheritedGenerator + ? this.beanNameGenerator + : BeanUtils.instantiateClass(generatorClass)); ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy"); if (scopedProxyMode != ScopedProxyMode.DEFAULT) { 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 23dcbe6ef05..02b4125e611 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 @@ -49,6 +49,7 @@ import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata; import org.springframework.core.type.MethodMetadata; import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.util.Assert; import org.springframework.util.StringUtils; import static org.springframework.context.annotation.MetadataUtils.*; @@ -82,7 +83,7 @@ class ConfigurationClassBeanDefinitionReader { private final Environment environment; - private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator(); + private final BeanNameGenerator beanNameGenerator; /** @@ -91,16 +92,20 @@ class ConfigurationClassBeanDefinitionReader { * @param problemReporter * @param metadataReaderFactory */ - public ConfigurationClassBeanDefinitionReader(BeanDefinitionRegistry registry, SourceExtractor sourceExtractor, + public ConfigurationClassBeanDefinitionReader( + BeanDefinitionRegistry registry, SourceExtractor sourceExtractor, ProblemReporter problemReporter, MetadataReaderFactory metadataReaderFactory, - ResourceLoader resourceLoader, Environment environment) { + ResourceLoader resourceLoader, Environment environment, + BeanNameGenerator beanNameGenerator) { + Assert.notNull(beanNameGenerator, "BeanNameGenerator must not be null"); this.registry = registry; this.sourceExtractor = sourceExtractor; this.problemReporter = problemReporter; this.metadataReaderFactory = metadataReaderFactory; this.resourceLoader = resourceLoader; this.environment = environment; + this.beanNameGenerator = beanNameGenerator; } 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 0825b134dba..1ad4838ed88 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 @@ -36,6 +36,7 @@ import org.springframework.beans.factory.parsing.Problem; import org.springframework.beans.factory.parsing.ProblemReporter; import org.springframework.beans.factory.support.BeanDefinitionReader; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.env.Environment; import org.springframework.core.env.PropertySource; @@ -100,14 +101,16 @@ class ConfigurationClassParser { */ public ConfigurationClassParser(MetadataReaderFactory metadataReaderFactory, ProblemReporter problemReporter, Environment environment, - ResourceLoader resourceLoader, BeanDefinitionRegistry registry) { + ResourceLoader resourceLoader, BeanNameGenerator beanNameGenerator, + BeanDefinitionRegistry registry) { + this.metadataReaderFactory = metadataReaderFactory; this.problemReporter = problemReporter; this.environment = environment; this.resourceLoader = resourceLoader; this.registry = registry; - this.componentScanParser = - new ComponentScanAnnotationParser(this.resourceLoader, this.environment, this.registry); + this.componentScanParser = new ComponentScanAnnotationParser( + resourceLoader, environment, beanNameGenerator, registry); } diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java index 8e724106de8..9736099c6f5 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java @@ -46,6 +46,7 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; +import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.EnvironmentAware; import org.springframework.context.ResourceLoaderAware; @@ -65,6 +66,8 @@ import org.springframework.core.type.classreading.SimpleMetadataReaderFactory; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; +import static org.springframework.context.annotation.AnnotationConfigUtils.*; + /** * {@link BeanFactoryPostProcessor} used for bootstrapping processing of * {@link Configuration @Configuration} classes. @@ -112,6 +115,8 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo private ConfigurationClassBeanDefinitionReader reader; + private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator(); + /** * Set the {@link SourceExtractor} to use for generated bean definitions @@ -142,6 +147,26 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo this.setMetadataReaderFactoryCalled = true; } + /** + * Set the {@link BeanNameGenerator} to be used when registering imported and nested + * {@link Configuration} classes. The default is {@link AnnotationBeanNameGenerator}. + *
Note that this strategy does not apply to {@link Bean} methods. + *
This setter is typically only appropriate when configuring the post-processor as
+ * a standalone bean definition in XML, e.g. not using the dedicated
+ * {@code AnnotationConfig*} application contexts or the {@code
+ *