Make use of bean definition overriding more visible

This commit makes the use of bean definition overriding more visible and
prepare for a deprecation of the feature in the next major release.

As of this commit, use of bean definition overriding logs at INFO level.
The previous log level can be restored by setting the
allowBeanDefinitionOverriding flag explicitly on the BeanFactory (or
via the related ApplicationContext).

A number of tests that are using bean overriding on purpose have been
updated to set this flag, which will make them easier to find once we
actually deprecate the feature.

Closes gh-31288
This commit is contained in:
Stéphane Nicoll
2024-03-25 09:53:18 +01:00
parent 8af3eb1aea
commit 7a74e45946
17 changed files with 186 additions and 71 deletions

View File

@@ -840,6 +840,7 @@ class DefaultListableBeanFactoryTests {
@Test
void aliasCircle() {
lbf.setAllowBeanDefinitionOverriding(true);
lbf.registerAlias("test", "test2");
lbf.registerAlias("test2", "test3");
@@ -867,6 +868,7 @@ class DefaultListableBeanFactoryTests {
@Test
void beanDefinitionOverriding() {
lbf.setAllowBeanDefinitionOverriding(true);
lbf.registerBeanDefinition("test", new RootBeanDefinition(TestBean.class));
lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class));
lbf.registerAlias("otherTest", "test2");
@@ -906,6 +908,7 @@ class DefaultListableBeanFactoryTests {
@Test
void beanDefinitionOverridingWithAlias() {
lbf.setAllowBeanDefinitionOverriding(true);
lbf.registerBeanDefinition("test", new RootBeanDefinition(TestBean.class));
lbf.registerAlias("test", "testAlias");
lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class));
@@ -917,6 +920,7 @@ class DefaultListableBeanFactoryTests {
@Test
void beanDefinitionOverridingWithConstructorArgumentMismatch() {
lbf.setAllowBeanDefinitionOverriding(true);
RootBeanDefinition bd1 = new RootBeanDefinition(NestedTestBean.class);
bd1.getConstructorArgumentValues().addIndexedArgumentValue(1, "value1");
lbf.registerBeanDefinition("test", bd1);
@@ -1196,6 +1200,7 @@ class DefaultListableBeanFactoryTests {
@Test
void reregisterBeanDefinition() {
lbf.setAllowBeanDefinitionOverriding(true);
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
bd1.setScope(BeanDefinition.SCOPE_PROTOTYPE);
lbf.registerBeanDefinition("testBean", bd1);
@@ -1306,6 +1311,7 @@ class DefaultListableBeanFactoryTests {
@Test
void withOverloadedSetters() {
lbf.setAllowBeanDefinitionOverriding(true);
RootBeanDefinition rbd = new RootBeanDefinition(SetterOverload.class);
rbd.getPropertyValues().add("object", "a String");
lbf.registerBeanDefinition("overloaded", rbd);

View File

@@ -16,7 +16,6 @@
package org.springframework.beans.factory.annotation;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.BeanDefinition;
@@ -33,25 +32,9 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
*/
class LookupAnnotationTests {
private DefaultListableBeanFactory beanFactory;
@BeforeEach
void setup() {
beanFactory = new DefaultListableBeanFactory();
AutowiredAnnotationBeanPostProcessor aabpp = new AutowiredAnnotationBeanPostProcessor();
aabpp.setBeanFactory(beanFactory);
beanFactory.addBeanPostProcessor(aabpp);
beanFactory.registerBeanDefinition("abstractBean", new RootBeanDefinition(AbstractBean.class));
beanFactory.registerBeanDefinition("beanConsumer", new RootBeanDefinition(BeanConsumer.class));
RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class);
tbd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
beanFactory.registerBeanDefinition("testBean", tbd);
}
@Test
void testWithoutConstructorArg() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean");
Object expected = bean.get();
assertThat(expected.getClass()).isEqualTo(TestBean.class);
@@ -60,6 +43,7 @@ class LookupAnnotationTests {
@Test
void testWithOverloadedArg() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean");
TestBean expected = bean.get("haha");
assertThat(expected.getClass()).isEqualTo(TestBean.class);
@@ -69,6 +53,7 @@ class LookupAnnotationTests {
@Test
void testWithOneConstructorArg() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean");
TestBean expected = bean.getOneArgument("haha");
assertThat(expected.getClass()).isEqualTo(TestBean.class);
@@ -78,6 +63,7 @@ class LookupAnnotationTests {
@Test
void testWithTwoConstructorArg() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean");
TestBean expected = bean.getTwoArguments("haha", 72);
assertThat(expected.getClass()).isEqualTo(TestBean.class);
@@ -88,6 +74,7 @@ class LookupAnnotationTests {
@Test
void testWithThreeArgsShouldFail() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
AbstractBean bean = (AbstractBean) beanFactory.getBean("abstractBean");
assertThatExceptionOfType(AbstractMethodError.class).as("TestBean has no three arg constructor").isThrownBy(() ->
bean.getThreeArguments("name", 1, 2));
@@ -96,6 +83,7 @@ class LookupAnnotationTests {
@Test
void testWithEarlyInjection() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
AbstractBean bean = beanFactory.getBean("beanConsumer", BeanConsumer.class).abstractBean;
Object expected = bean.get();
assertThat(expected.getClass()).isEqualTo(TestBean.class);
@@ -106,7 +94,7 @@ class LookupAnnotationTests {
public void testWithNullBean() {
RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class, () -> null);
tbd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
beanFactory.registerBeanDefinition("testBean", tbd);
DefaultListableBeanFactory beanFactory = configureBeanFactory(tbd);
AbstractBean bean = beanFactory.getBean("beanConsumer", BeanConsumer.class).abstractBean;
Object expected = bean.get();
@@ -116,6 +104,7 @@ class LookupAnnotationTests {
@Test
void testWithGenericBean() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
beanFactory.registerBeanDefinition("numberBean", new RootBeanDefinition(NumberBean.class));
beanFactory.registerBeanDefinition("doubleStore", new RootBeanDefinition(DoubleStore.class));
beanFactory.registerBeanDefinition("floatStore", new RootBeanDefinition(FloatStore.class));
@@ -127,6 +116,7 @@ class LookupAnnotationTests {
@Test
void testSingletonWithoutMetadataCaching() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
beanFactory.setCacheBeanMetadata(false);
beanFactory.registerBeanDefinition("numberBean", new RootBeanDefinition(NumberBean.class));
@@ -140,6 +130,7 @@ class LookupAnnotationTests {
@Test
void testPrototypeWithoutMetadataCaching() {
DefaultListableBeanFactory beanFactory = configureBeanFactory();
beanFactory.setCacheBeanMetadata(false);
beanFactory.registerBeanDefinition("numberBean", new RootBeanDefinition(NumberBean.class, BeanDefinition.SCOPE_PROTOTYPE, null));
@@ -155,6 +146,23 @@ class LookupAnnotationTests {
assertThat(beanFactory.getBean(FloatStore.class)).isSameAs(bean.getFloatStore());
}
private DefaultListableBeanFactory configureBeanFactory(RootBeanDefinition tbd) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
AutowiredAnnotationBeanPostProcessor aabpp = new AutowiredAnnotationBeanPostProcessor();
aabpp.setBeanFactory(beanFactory);
beanFactory.addBeanPostProcessor(aabpp);
beanFactory.registerBeanDefinition("abstractBean", new RootBeanDefinition(AbstractBean.class));
beanFactory.registerBeanDefinition("beanConsumer", new RootBeanDefinition(BeanConsumer.class));
beanFactory.registerBeanDefinition("testBean", tbd);
return beanFactory;
}
private DefaultListableBeanFactory configureBeanFactory() {
RootBeanDefinition tbd = new RootBeanDefinition(TestBean.class);
tbd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
return configureBeanFactory(tbd);
}
public abstract static class AbstractBean {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,6 +52,7 @@ class DuplicateBeanIdTests {
@Test
void duplicateBeanIdsAcrossNestingLevels() {
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.setAllowBeanDefinitionOverriding(true);
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
reader.loadBeanDefinitions(new ClassPathResource("DuplicateBeanIdTests-multiLevel-context.xml", this.getClass()));
TestBean testBean = bf.getBean(TestBean.class); // there should be only one

View File

@@ -51,6 +51,7 @@ class NestedBeansElementTests {
env.setActiveProfiles("dev");
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
bf.setAllowBeanDefinitionOverriding(true);
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(bf);
reader.setEnvironment(env);
reader.loadBeanDefinitions(XML);