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 c49e5736b1..722c35baf0 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 @@ -298,16 +298,12 @@ class ConfigurationClassBeanDefinitionReader { } BeanDefinition existingBeanDef = this.registry.getBeanDefinition(beanName); - // Is the existing bean definition one that was created from a configuration class? - // -> allow the current bean method to override, since both are at second-pass level. - // However, if the bean method is an overloaded case on the same configuration class, - // preserve the existing bean definition. + // If the bean method is an overloaded case on the same configuration class, + // preserve the existing bean definition and mark it as overloaded. if (existingBeanDef instanceof ConfigurationClassBeanDefinition ccbd) { - if (ccbd.getMetadata().getClassName().equals( - beanMethod.getConfigurationClass().getMetadata().getClassName())) { - if (ccbd.getFactoryMethodMetadata().getMethodName().equals(ccbd.getFactoryMethodName())) { - ccbd.setNonUniqueFactoryMethodName(ccbd.getFactoryMethodMetadata().getMethodName()); - } + if (ccbd.getMetadata().getClassName().equals(beanMethod.getConfigurationClass().getMetadata().getClassName()) && + ccbd.getFactoryMethodMetadata().getMethodName().equals(beanMethod.getMetadata().getMethodName())) { + ccbd.setNonUniqueFactoryMethodName(ccbd.getFactoryMethodMetadata().getMethodName()); return true; } else { diff --git a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassProcessingTests.java b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassProcessingTests.java index 7a860fb173..033fe6d2ec 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassProcessingTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ConfigurationClassProcessingTests.java @@ -41,6 +41,7 @@ import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.DependencyDescriptor; import org.springframework.beans.factory.config.ListFactoryBean; import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; +import org.springframework.beans.factory.support.BeanDefinitionOverrideException; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.testfixture.beans.ITestBean; @@ -219,6 +220,12 @@ class ConfigurationClassProcessingTests { assertThat(foo.getSpouse()).isNull(); } + @Test // gh-33330 + void configurationWithMethodNameMismatch() { + assertThatExceptionOfType(BeanDefinitionOverrideException.class) + .isThrownBy(() -> initBeanFactory(ConfigWithMethodNameMismatch.class)); + } + @Test void configurationWithAdaptivePrototypes() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); @@ -352,6 +359,7 @@ class ConfigurationClassProcessingTests { String configBeanName = configClass.getName(); factory.registerBeanDefinition(configBeanName, new RootBeanDefinition(configClass)); } + factory.setAllowBeanDefinitionOverriding(false); ConfigurationClassPostProcessor ccpp = new ConfigurationClassPostProcessor(); ccpp.postProcessBeanDefinitionRegistry(factory); ccpp.postProcessBeanFactory(factory); @@ -526,6 +534,19 @@ class ConfigurationClassProcessingTests { } + @Configuration + static class ConfigWithMethodNameMismatch { + + @Bean(name = "foo") public TestBean foo() { + return new SpousyTestBean("foo"); + } + + @Bean(name = "foo") public TestBean fooX() { + return new SpousyTestBean("fooX"); + } + } + + @Scope("prototype") static class AdaptiveInjectionPoints {