diff --git a/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessor.java b/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessor.java index 141be2976b..a257a07aba 100644 --- a/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessor.java +++ b/spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessor.java @@ -148,14 +148,17 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor, // Process existing bean definition. if (existingBeanDefinition != null) { validateBeanDefinition(beanFactory, beanName); - copyBeanDefinitionProperties(existingBeanDefinition, pseudoBeanDefinition); + // Since validation may have registered a singleton as a side effect -- for example, + // for a FactoryBean -- we need to remove the bean definition (which removes the + // singleton as a side effect) and re-register the bean definition. registry.removeBeanDefinition(beanName); + registry.registerBeanDefinition(beanName, existingBeanDefinition); + } + else { + // There was no existing bean definition, so we register the pseudo bean definition + // to ensure that a bean definition exists for the given bean name. + registry.registerBeanDefinition(beanName, pseudoBeanDefinition); } - - // At this point, we either removed an existing bean definition above, or - // there was no bean definition to begin with. So, we register the pseudo bean - // definition to ensure that a bean definition exists for the given bean name. - registry.registerBeanDefinition(beanName, pseudoBeanDefinition); Object override = overrideMetadata.createOverride(beanName, existingBeanDefinition, null); overrideMetadata.track(override, beanFactory); @@ -294,16 +297,6 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor, () -> "Unable to override bean '" + beanName + "': only singleton beans can be overridden."); } - /** - * Copy the following properties of the source {@link BeanDefinition} to the - * target: the {@linkplain BeanDefinition#isPrimary() primary flag} and the - * {@linkplain BeanDefinition#isFallback() fallback flag}. - */ - private static void copyBeanDefinitionProperties(BeanDefinition source, RootBeanDefinition target) { - target.setPrimary(source.isPrimary()); - target.setFallback(source.isFallback()); - } - static class WrapEarlyBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor, PriorityOrdered { diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessorTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessorTests.java index 864d5f2f90..f7802d0fdd 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessorTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/BeanOverrideBeanFactoryPostProcessorTests.java @@ -315,7 +315,6 @@ class BeanOverrideBeanFactoryPostProcessorTests { assertThatNoException().isThrownBy(context::refresh); assertThat(context.getBeanDefinition("descriptionBean")) - .isNotSameAs(definition) .matches(BeanDefinition::isPrimary, "isPrimary") .matches(BeanDefinition::isFallback, "isFallback") .satisfies(d -> assertThat(d.getScope()).isEqualTo("")) @@ -324,9 +323,8 @@ class BeanOverrideBeanFactoryPostProcessorTests { } @Test - void qualifiedElementIsSetToBeanOverrideField() { + void qualifiedElementIsSetToBeanOverrideFieldForNonexistentBeanDefinition() { AnnotationConfigApplicationContext context = createContext(CaseByNameWithQualifier.class); - context.registerBeanDefinition("descriptionBean", new RootBeanDefinition(String.class, () -> "ORIGINAL")); assertThatNoException().isThrownBy(context::refresh); assertThat(context.getBeanDefinition("descriptionBean")) @@ -398,9 +396,12 @@ class BeanOverrideBeanFactoryPostProcessorTests { static class CaseByNameWithQualifier { @Qualifier("preferThis") - @DummyBean(beanName = "descriptionBean") + @TestBean(name = "descriptionBean", enforceOverride = false) private String description; + static String descriptionBean() { + return "overridden"; + } } static class TestFactoryBean implements FactoryBean {