Skip to content

Commit 0a42c80

Browse files
jhoellerunknown
authored andcommitted
@import'ed configuration classes get properly registered in case of same class name (second try)
Issue: SPR-9243
1 parent 34c3e82 commit 0a42c80

File tree

5 files changed

+60
-55
lines changed

5 files changed

+60
-55
lines changed

spring-context/src/main/java/org/springframework/context/annotation/AnnotatedBeanDefinitionReader.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public class AnnotatedBeanDefinitionReader {
5252

5353
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
5454

55+
5556
/**
5657
* Create a new {@code AnnotatedBeanDefinitionReader} for the given registry.
5758
* If the registry is {@link EnvironmentCapable}, e.g. is an {@code ApplicationContext},
@@ -78,10 +79,8 @@ public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
7879
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
7980
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
8081
Assert.notNull(environment, "Environment must not be null");
81-
8282
this.registry = registry;
8383
this.environment = environment;
84-
8584
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
8685
}
8786

@@ -115,8 +114,8 @@ public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
115114
* <p>The default is an {@link AnnotationScopeMetadataResolver}.
116115
*/
117116
public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
118-
this.scopeMetadataResolver = (scopeMetadataResolver != null ? scopeMetadataResolver
119-
: new AnnotationScopeMetadataResolver());
117+
this.scopeMetadataResolver =
118+
(scopeMetadataResolver != null ? scopeMetadataResolver : new AnnotationScopeMetadataResolver());
120119
}
121120

122121
public void register(Class<?>... annotatedClasses) {
@@ -136,7 +135,6 @@ public void registerBean(Class<?> annotatedClass, Class<? extends Annotation>...
136135
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
137136
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
138137
AnnotationMetadata metadata = abd.getMetadata();
139-
140138
if (metadata.isAnnotated(Profile.class.getName())) {
141139
AnnotationAttributes profile = MetadataUtils.attributesFor(metadata, Profile.class);
142140
if (!this.environment.acceptsProfiles(profile.getStringArray("value"))) {
@@ -151,9 +149,11 @@ public void registerBean(Class<?> annotatedClass, String name, Class<? extends A
151149
for (Class<? extends Annotation> qualifier : qualifiers) {
152150
if (Primary.class.equals(qualifier)) {
153151
abd.setPrimary(true);
154-
} else if (Lazy.class.equals(qualifier)) {
152+
}
153+
else if (Lazy.class.equals(qualifier)) {
155154
abd.setLazyInit(true);
156-
} else {
155+
}
156+
else {
157157
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
158158
}
159159
}

spring-context/src/main/java/org/springframework/context/annotation/AnnotationBeanNameGenerator.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import java.util.Map;
2121
import java.util.Set;
2222

23-
import org.springframework.beans.factory.BeanFactoryUtils;
2423
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
2524
import org.springframework.beans.factory.config.BeanDefinition;
2625
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@@ -122,22 +121,13 @@ protected boolean isStereotypeWithNameValue(String annotationType,
122121

123122
/**
124123
* Derive a default bean name from the given bean definition.
125-
* <p>The default implementation delegates to {@link #buildDefaultBeanName(BeanDefinition)},
126-
* appending a counter suffix if necessary to make the bean name unique in the given registry.
124+
* <p>The default implementation delegates to {@link #buildDefaultBeanName(BeanDefinition)}.
127125
* @param definition the bean definition to build a bean name for
128126
* @param registry the registry that the given bean definition is being registered with
129127
* @return the default bean name (never <code>null</code>)
130128
*/
131129
protected String buildDefaultBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
132-
String generatedName = buildDefaultBeanName(definition);
133-
// Increase counter until the id is unique.
134-
String id = generatedName;
135-
int counter = 0;
136-
while (registry.containsBeanDefinition(id)) {
137-
counter++;
138-
id = generatedName + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + counter;
139-
}
140-
return id;
130+
return buildDefaultBeanName(definition);
141131
}
142132

143133
/**

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@
4949
import org.springframework.core.type.AnnotationMetadata;
5050
import org.springframework.core.type.MethodMetadata;
5151
import org.springframework.core.type.classreading.MetadataReaderFactory;
52-
import org.springframework.util.Assert;
5352
import org.springframework.util.StringUtils;
5453

5554
import static org.springframework.context.annotation.MetadataUtils.*;
@@ -83,29 +82,25 @@ class ConfigurationClassBeanDefinitionReader {
8382

8483
private final Environment environment;
8584

86-
private final BeanNameGenerator beanNameGenerator;
85+
private final BeanNameGenerator importBeanNameGenerator;
8786

8887

8988
/**
9089
* Create a new {@link ConfigurationClassBeanDefinitionReader} instance that will be used
9190
* to populate the given {@link BeanDefinitionRegistry}.
92-
* @param problemReporter
93-
* @param metadataReaderFactory
9491
*/
9592
public ConfigurationClassBeanDefinitionReader(
9693
BeanDefinitionRegistry registry, SourceExtractor sourceExtractor,
9794
ProblemReporter problemReporter, MetadataReaderFactory metadataReaderFactory,
98-
ResourceLoader resourceLoader, Environment environment,
99-
BeanNameGenerator beanNameGenerator) {
95+
ResourceLoader resourceLoader, Environment environment, BeanNameGenerator importBeanNameGenerator) {
10096

101-
Assert.notNull(beanNameGenerator, "BeanNameGenerator must not be null");
10297
this.registry = registry;
10398
this.sourceExtractor = sourceExtractor;
10499
this.problemReporter = problemReporter;
105100
this.metadataReaderFactory = metadataReaderFactory;
106101
this.resourceLoader = resourceLoader;
107102
this.environment = environment;
108-
this.beanNameGenerator = beanNameGenerator;
103+
this.importBeanNameGenerator = importBeanNameGenerator;
109104
}
110105

111106

@@ -124,7 +119,9 @@ public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
124119
* class itself, all its {@link Bean} methods
125120
*/
126121
private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass) {
127-
doLoadBeanDefinitionForConfigurationClassIfNecessary(configClass);
122+
if (configClass.isImported()) {
123+
registerBeanDefinitionForImportedConfigurationClass(configClass);
124+
}
128125
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
129126
loadBeanDefinitionsForBeanMethod(beanMethod);
130127
}
@@ -134,17 +131,13 @@ private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configC
134131
/**
135132
* Register the {@link Configuration} class itself as a bean definition.
136133
*/
137-
private void doLoadBeanDefinitionForConfigurationClassIfNecessary(ConfigurationClass configClass) {
138-
if (!configClass.isImported()) {
139-
return;
140-
}
141-
134+
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
142135
AnnotationMetadata metadata = configClass.getMetadata();
143136
BeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
144137
String className = metadata.getClassName();
145138
configBeanDef.setBeanClassName(className);
146139
if (ConfigurationClassUtils.checkConfigurationClassCandidate(configBeanDef, this.metadataReaderFactory)) {
147-
String configBeanName = this.beanNameGenerator.generateBeanName(configBeanDef, this.registry);
140+
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
148141
this.registry.registerBeanDefinition(configBeanName, configBeanDef);
149142
configClass.setBeanName(configBeanName);
150143
if (logger.isDebugEnabled()) {

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,17 +101,16 @@ class ConfigurationClassParser {
101101
* to populate the set of configuration classes.
102102
*/
103103
public ConfigurationClassParser(MetadataReaderFactory metadataReaderFactory,
104-
ProblemReporter problemReporter, Environment environment,
105-
ResourceLoader resourceLoader, BeanNameGenerator beanNameGenerator,
106-
BeanDefinitionRegistry registry) {
104+
ProblemReporter problemReporter, Environment environment, ResourceLoader resourceLoader,
105+
BeanNameGenerator componentScanBeanNameGenerator, BeanDefinitionRegistry registry) {
107106

108107
this.metadataReaderFactory = metadataReaderFactory;
109108
this.problemReporter = problemReporter;
110109
this.environment = environment;
111110
this.resourceLoader = resourceLoader;
112111
this.registry = registry;
113112
this.componentScanParser = new ComponentScanAnnotationParser(
114-
resourceLoader, environment, beanNameGenerator, registry);
113+
resourceLoader, environment, componentScanBeanNameGenerator, registry);
115114
}
116115

117116

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassPostProcessor.java

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
import org.springframework.beans.factory.parsing.ProblemReporter;
4444
import org.springframework.beans.factory.parsing.SourceExtractor;
4545
import org.springframework.beans.factory.support.AbstractBeanDefinition;
46-
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
4746
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
4847
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
4948
import org.springframework.beans.factory.support.BeanNameGenerator;
@@ -88,6 +87,13 @@
8887
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
8988
ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
9089

90+
private static final String IMPORT_AWARE_PROCESSOR_BEAN_NAME =
91+
ConfigurationClassPostProcessor.class.getName() + ".importAwareProcessor";
92+
93+
private static final String IMPORT_REGISTRY_BEAN_NAME =
94+
ConfigurationClassPostProcessor.class.getName() + ".importRegistry";
95+
96+
9197
private final Log logger = LogFactory.getLog(getClass());
9298

9399
private SourceExtractor sourceExtractor = new PassThroughSourceExtractor();
@@ -110,7 +116,18 @@ public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPo
110116

111117
private ConfigurationClassBeanDefinitionReader reader;
112118

113-
private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
119+
private boolean localBeanNameGeneratorSet = false;
120+
121+
/* using short class names as default bean names */
122+
private BeanNameGenerator componentScanBeanNameGenerator = new AnnotationBeanNameGenerator();
123+
124+
/* using fully qualified class names as default bean names */
125+
private BeanNameGenerator importBeanNameGenerator = new AnnotationBeanNameGenerator() {
126+
@Override
127+
protected String buildDefaultBeanName(BeanDefinition definition) {
128+
return definition.getBeanClassName();
129+
}
130+
};
114131

115132

116133
/**
@@ -143,23 +160,27 @@ public void setMetadataReaderFactory(MetadataReaderFactory metadataReaderFactory
143160
}
144161

145162
/**
146-
* Set the {@link BeanNameGenerator} to be used when registering imported and nested
147-
* {@link Configuration} classes. The default is {@link AnnotationBeanNameGenerator}.
163+
* Set the {@link BeanNameGenerator} to be used when triggering component scanning
164+
* from {@link Configuration} classes and when registering {@link Import}'ed
165+
* configuration classes. The default is a standard {@link AnnotationBeanNameGenerator}
166+
* for scanned components (compatible with the default in {@link ClassPathBeanDefinitionScanner})
167+
* and a variant thereof for imported configuration classes (using unique fully-qualified
168+
* class names instead of standard component overriding).
148169
* <p>Note that this strategy does <em>not</em> apply to {@link Bean} methods.
149170
* <p>This setter is typically only appropriate when configuring the post-processor as
150171
* a standalone bean definition in XML, e.g. not using the dedicated
151172
* {@code AnnotationConfig*} application contexts or the {@code
152173
* <context:annotation-config>} element. Any bean name generator specified against
153174
* the application context will take precedence over any value set here.
154-
* @param beanNameGenerator the strategy to use when generating configuration class
155-
* bean names
156175
* @since 3.1.1
157176
* @see AnnotationConfigApplicationContext#setBeanNameGenerator(BeanNameGenerator)
158177
* @see AnnotationConfigUtils#CONFIGURATION_BEAN_NAME_GENERATOR
159178
*/
160179
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
161180
Assert.notNull(beanNameGenerator, "BeanNameGenerator must not be null");
162-
this.beanNameGenerator = beanNameGenerator;
181+
this.localBeanNameGeneratorSet = true;
182+
this.componentScanBeanNameGenerator = beanNameGenerator;
183+
this.importBeanNameGenerator = beanNameGenerator;
163184
}
164185

165186
public void setEnvironment(Environment environment) {
@@ -184,7 +205,8 @@ public void setBeanClassLoader(ClassLoader beanClassLoader) {
184205
* Derive further bean definitions from the configuration classes in the registry.
185206
*/
186207
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
187-
BeanDefinitionReaderUtils.registerWithGeneratedName(new RootBeanDefinition(ImportAwareBeanPostProcessor.class), registry);
208+
registry.registerBeanDefinition(IMPORT_AWARE_PROCESSOR_BEAN_NAME,
209+
new RootBeanDefinition(ImportAwareBeanPostProcessor.class));
188210
int registryId = System.identityHashCode(registry);
189211
if (this.registriesPostProcessed.contains(registryId)) {
190212
throw new IllegalStateException(
@@ -239,15 +261,17 @@ public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
239261
SingletonBeanRegistry singletonRegistry = null;
240262
if (registry instanceof SingletonBeanRegistry) {
241263
singletonRegistry = (SingletonBeanRegistry) registry;
242-
if (singletonRegistry.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
243-
this.beanNameGenerator = (BeanNameGenerator) singletonRegistry.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
264+
if (!this.localBeanNameGeneratorSet && singletonRegistry.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
265+
BeanNameGenerator generator = (BeanNameGenerator) singletonRegistry.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
266+
this.componentScanBeanNameGenerator = generator;
267+
this.importBeanNameGenerator = generator;
244268
}
245269
}
246270

247271
// Parse each @Configuration class
248272
ConfigurationClassParser parser = new ConfigurationClassParser(
249273
this.metadataReaderFactory, this.problemReporter, this.environment,
250-
this.resourceLoader, this.beanNameGenerator, registry);
274+
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
251275
for (BeanDefinitionHolder holder : configCandidates) {
252276
BeanDefinition bd = holder.getBeanDefinition();
253277
try {
@@ -282,16 +306,15 @@ public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
282306
// Read the model and create bean definitions based on its content
283307
if (this.reader == null) {
284308
this.reader = new ConfigurationClassBeanDefinitionReader(
285-
registry, this.sourceExtractor, this.problemReporter,
286-
this.metadataReaderFactory, this.resourceLoader, this.environment,
287-
this.beanNameGenerator);
309+
registry, this.sourceExtractor, this.problemReporter, this.metadataReaderFactory,
310+
this.resourceLoader, this.environment, this.importBeanNameGenerator);
288311
}
289312
this.reader.loadBeanDefinitions(parser.getConfigurationClasses());
290313

291314
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
292315
if (singletonRegistry != null) {
293-
if (!singletonRegistry.containsSingleton("importRegistry")) {
294-
singletonRegistry.registerSingleton("importRegistry", parser.getImportRegistry());
316+
if (!singletonRegistry.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
317+
singletonRegistry.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
295318
}
296319
}
297320
}
@@ -349,7 +372,7 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
349372

350373
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
351374
if (bean instanceof ImportAware) {
352-
ImportRegistry importRegistry = beanFactory.getBean(ImportRegistry.class);
375+
ImportRegistry importRegistry = this.beanFactory.getBean(IMPORT_REGISTRY_BEAN_NAME, ImportRegistry.class);
353376
String importingClass = importRegistry.getImportingClassFor(bean.getClass().getSuperclass().getName());
354377
if (importingClass != null) {
355378
try {

0 commit comments

Comments
 (0)