diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationBeanNameGenerator.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationBeanNameGenerator.java index b40ada4e5ec..4c8bfeaee7d 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationBeanNameGenerator.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationBeanNameGenerator.java @@ -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. + *
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); diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java index a5f64e71afe..e9eb836abe5 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java @@ -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++) { diff --git a/spring-context/src/main/java/org/springframework/context/annotation/FullyQualifiedConfigurationBeanNameGenerator.java b/spring-context/src/main/java/org/springframework/context/annotation/FullyQualifiedConfigurationBeanNameGenerator.java index 68e88ebfab2..858a02bdb47 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/FullyQualifiedConfigurationBeanNameGenerator.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/FullyQualifiedConfigurationBeanNameGenerator.java @@ -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. + * + *
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
diff --git a/spring-context/src/test/java/org/springframework/context/annotation/AnnotationConfigApplicationContextTests.java b/spring-context/src/test/java/org/springframework/context/annotation/AnnotationConfigApplicationContextTests.java
index 1864d8899e3..ae774623fb9 100644
--- a/spring-context/src/test/java/org/springframework/context/annotation/AnnotationConfigApplicationContextTests.java
+++ b/spring-context/src/test/java/org/springframework/context/annotation/AnnotationConfigApplicationContextTests.java
@@ -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