mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-17 08:24:13 +00:00
Register original bean name as alias if not taken already
Closes gh-37038
This commit is contained in:
+4
-2
@@ -38,9 +38,11 @@ public interface ConfigurationBeanNameGenerator extends BeanNameGenerator {
|
||||
/**
|
||||
* Derive a default bean name for the given {@link Bean @Bean} method,
|
||||
* taking into account the specified {@link Bean#name() name} attribute.
|
||||
* <p>As of 7.1, the original {@code @Bean} name (typically the method name)
|
||||
* will be registered as an alias if that name has not been taken already.
|
||||
* @param beanMethod the method metadata for the {@link Bean @Bean} method
|
||||
* @param beanName the {@link Bean#name() name} attribute or {@code null} if
|
||||
* none is specified
|
||||
* @param beanName the {@link Bean#name() name} attribute or {@code null}
|
||||
* if none is specified
|
||||
* @return the default bean name to use
|
||||
*/
|
||||
String deriveBeanName(MethodMetadata beanMethod, @Nullable String beanName);
|
||||
|
||||
+5
@@ -210,6 +210,11 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
String localBeanName = defaultBeanName(beanName, methodName);
|
||||
beanName = (this.importBeanNameGenerator instanceof ConfigurationBeanNameGenerator cbng ?
|
||||
cbng.deriveBeanName(metadata, beanName) : localBeanName);
|
||||
if (!localBeanName.equals(beanName) && !this.registry.containsBeanDefinition(localBeanName) &&
|
||||
!this.registry.isAlias(localBeanName)) {
|
||||
// Register original name as alias unless registered already.
|
||||
this.registry.registerAlias(beanName, localBeanName);
|
||||
}
|
||||
if (explicitNames.length > 0) {
|
||||
// Register aliases even when overridden below.
|
||||
for (int i = 1; i < explicitNames.length; i++) {
|
||||
|
||||
+7
-4
@@ -32,10 +32,13 @@ import org.springframework.core.type.MethodMetadata;
|
||||
* {@code @Bean} methods (which uses the plain method name), primarily for use
|
||||
* in large applications with potential bean name overlaps. Favor this bean
|
||||
* naming strategy over {@code FullyQualifiedAnnotationBeanNameGenerator} if
|
||||
* you expect such naming conflicts for {@code @Bean} methods, as long as the
|
||||
* application does not depend on {@code @Bean} method names as bean names.
|
||||
* Where the name does matter, make sure to declare {@code @Bean("myBeanName")}
|
||||
* in such a scenario, even if it repeats the method name as the bean name.
|
||||
* you expect such naming conflicts for {@code @Bean} methods.
|
||||
*
|
||||
* <p>As of 7.1, the original {@code @Bean} method name will be registered
|
||||
* as an alias if that name has not been taken already: effectively on first
|
||||
* occurrence, whereas any later {@code @Bean} methods of the same name will
|
||||
* not have aliases applied. This preserves the availability of common beans
|
||||
* under the original bean names for retrieval and injection purposes.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 7.0
|
||||
|
||||
+29
@@ -105,10 +105,31 @@ class AnnotationConfigApplicationContextTests {
|
||||
context.getBean(Config.class.getName() + ".testBean");
|
||||
assertThat(context.getBean(NameConfig.class.getName() + ".name")).isEqualTo("foo");
|
||||
assertThat(context.getBean(NameConfig.class.getName() + ".prefixName")).isEqualTo("barfoo");
|
||||
assertThat(context.getBean("name")).isEqualTo("foo");
|
||||
assertThat(context.getBean("prefixName")).isEqualTo("barfoo");
|
||||
Map<String, Object> beans = context.getBeansWithAnnotation(Configuration.class);
|
||||
assertThat(beans).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerAndRefreshWithOverlappingFullyQualifiedBeanNames() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.setBeanNameGenerator(FullyQualifiedConfigurationBeanNameGenerator.INSTANCE);
|
||||
context.setAllowBeanDefinitionOverriding(false);
|
||||
context.register(Config.class, NameConfig.class, OtherNameConfig.class);
|
||||
context.refresh();
|
||||
|
||||
context.getBean(Config.class.getName() + ".testBean");
|
||||
assertThat(context.getBean(NameConfig.class.getName() + ".name")).isEqualTo("foo");
|
||||
assertThat(context.getBean(NameConfig.class.getName() + ".prefixName")).isEqualTo("barfoo");
|
||||
assertThat(context.getBean(OtherNameConfig.class.getName() + ".name")).isEqualTo("fooX");
|
||||
assertThat(context.getBean(OtherNameConfig.class.getName() + ".prefixName")).isEqualTo("barXfooX");
|
||||
assertThat(context.getBean("name")).isEqualTo("foo");
|
||||
assertThat(context.getBean("prefixName")).isEqualTo("barfoo");
|
||||
Map<String, Object> beans = context.getBeansWithAnnotation(Configuration.class);
|
||||
assertThat(beans).hasSize(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getBeansWithAnnotation() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
@@ -632,6 +653,14 @@ class AnnotationConfigApplicationContextTests {
|
||||
@Bean(autowireCandidate = false) String prefixName() { return "bar" + name(); }
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class OtherNameConfig {
|
||||
|
||||
@Bean String name() { return "fooX"; }
|
||||
|
||||
@Bean(autowireCandidate = false) String prefixName() { return "barX" + name(); }
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import(NameConfig.class)
|
||||
static class AutowiredConfig {
|
||||
|
||||
Reference in New Issue
Block a user