diff --git a/framework-docs/modules/ROOT/pages/core/beans/definition.adoc b/framework-docs/modules/ROOT/pages/core/beans/definition.adoc index 2141abd706f..ca6730e4074 100644 --- a/framework-docs/modules/ROOT/pages/core/beans/definition.adoc +++ b/framework-docs/modules/ROOT/pages/core/beans/definition.adoc @@ -73,7 +73,23 @@ runtime (concurrently with live access to the factory) is not officially support lead to concurrent access exceptions, inconsistent state in the bean container, or both. ==== +[[beans-definition-overriding]] +== Overriding Beans +Bean overriding is happening when a bean is registered using an identifier that is +already allocated. While bean overriding is possible, it makes the configuration harder +to read and this feature will be deprecated in a future release. + +To disable bean overriding altogether, you can set the `allowBeanDefinitionOverriding` +to `false` on the `ApplicationContext` before it is refreshed. In such setup, an +exception is thrown if bean overriding is used. + +By default, the container logs every bean overriding at `INFO` level so that you can +adapt your configuration accordingly. While not recommended, you can silence those logs +by setting the `allowBeanDefinitionOverriding` flag to `true`. + +NOTE: We acknowledge that overriding beans in a test is convenient, and there is +explicit support for this. For more details please refer to xref:testing/annotations/integration-spring/annotation-beanoverriding.adoc[this section]. [[beans-beanname]] == Naming Beans diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java index 32fecaa40da..384c2cbc49a 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java @@ -152,7 +152,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto private String serializationId; /** Whether to allow re-registration of a different definition with the same name. */ - private boolean allowBeanDefinitionOverriding = true; + @Nullable + private Boolean allowBeanDefinitionOverriding; /** Whether to allow eager class loading even for lazy-init beans. */ private boolean allowEagerClassLoading = true; @@ -259,7 +260,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto * @since 4.1.2 */ public boolean isAllowBeanDefinitionOverriding() { - return this.allowBeanDefinitionOverriding; + return !Boolean.FALSE.equals(this.allowBeanDefinitionOverriding); } /** @@ -1142,27 +1143,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto if (!isBeanDefinitionOverridable(beanName)) { throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } - else if (existingDefinition.getRole() < beanDefinition.getRole()) { - // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE - if (logger.isInfoEnabled()) { - logger.info("Overriding user-defined bean definition for bean '" + beanName + - "' with a framework-generated bean definition: replacing [" + - existingDefinition + "] with [" + beanDefinition + "]"); - } - } - else if (!beanDefinition.equals(existingDefinition)) { - if (logger.isDebugEnabled()) { - logger.debug("Overriding bean definition for bean '" + beanName + - "' with a different definition: replacing [" + existingDefinition + - "] with [" + beanDefinition + "]"); - } - } else { - if (logger.isTraceEnabled()) { - logger.trace("Overriding bean definition for bean '" + beanName + - "' with an equivalent definition: replacing [" + existingDefinition + - "] with [" + beanDefinition + "]"); - } + logBeanDefinitionOverriding(beanName, beanDefinition, existingDefinition); } this.beanDefinitionMap.put(beanName, beanDefinition); } @@ -1217,6 +1199,44 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto } } + private void logBeanDefinitionOverriding(String beanName, BeanDefinition beanDefinition, + BeanDefinition existingDefinition) { + + boolean explicitBeanOverride = (this.allowBeanDefinitionOverriding != null); + if (existingDefinition.getRole() < beanDefinition.getRole()) { + // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE + if (logger.isInfoEnabled()) { + logger.info("Overriding user-defined bean definition for bean '" + beanName + + "' with a framework-generated bean definition: replacing [" + + existingDefinition + "] with [" + beanDefinition + "]"); + } + } + else if (!beanDefinition.equals(existingDefinition)) { + if (explicitBeanOverride && logger.isInfoEnabled()) { + logger.info("Overriding bean definition for bean '" + beanName + + "' with a different definition: replacing [" + existingDefinition + + "] with [" + beanDefinition + "]"); + } + if (logger.isDebugEnabled()) { + logger.debug("Overriding bean definition for bean '" + beanName + + "' with a different definition: replacing [" + existingDefinition + + "] with [" + beanDefinition + "]"); + } + } + else { + if (explicitBeanOverride && logger.isInfoEnabled()) { + logger.info("Overriding bean definition for bean '" + beanName + + "' with an equivalent definition: replacing [" + existingDefinition + + "] with [" + beanDefinition + "]"); + } + if (logger.isTraceEnabled()) { + logger.trace("Overriding bean definition for bean '" + beanName + + "' with an equivalent definition: replacing [" + existingDefinition + + "] with [" + beanDefinition + "]"); + } + } + } + @Override public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException { Assert.hasText(beanName, "'beanName' must not be empty"); diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java index a41a70e236b..80fe11af274 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java @@ -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); diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/LookupAnnotationTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/LookupAnnotationTests.java index f12e9a0fac6..6c058db6ca7 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/LookupAnnotationTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/LookupAnnotationTests.java @@ -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 { diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/xml/DuplicateBeanIdTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/xml/DuplicateBeanIdTests.java index 7ee14248ae4..8544568823f 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/xml/DuplicateBeanIdTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/xml/DuplicateBeanIdTests.java @@ -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 diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/xml/NestedBeansElementTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/xml/NestedBeansElementTests.java index 44cccf0b72f..38e90b31810 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/xml/NestedBeansElementTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/xml/NestedBeansElementTests.java @@ -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); diff --git a/spring-context-support/src/test/java/org/springframework/cache/jcache/config/JCacheCustomInterceptorTests.java b/spring-context-support/src/test/java/org/springframework/cache/jcache/config/JCacheCustomInterceptorTests.java index 27384ef73e5..8cc2254b155 100644 --- a/spring-context-support/src/test/java/org/springframework/cache/jcache/config/JCacheCustomInterceptorTests.java +++ b/spring-context-support/src/test/java/org/springframework/cache/jcache/config/JCacheCustomInterceptorTests.java @@ -24,6 +24,9 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; @@ -43,6 +46,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatRuntimeException; /** + * Tests that use a custom {@link JCacheInterceptor}. + * * @author Stephane Nicoll */ class JCacheCustomInterceptorTests { @@ -56,16 +61,19 @@ class JCacheCustomInterceptorTests { @BeforeEach void setup() { - ctx = new AnnotationConfigApplicationContext(EnableCachingConfig.class); + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + context.getBeanFactory().addBeanPostProcessor( + new CacheInterceptorBeanPostProcessor(context.getBeanFactory())); + context.register(EnableCachingConfig.class); + context.refresh(); + this.ctx = context; cs = ctx.getBean("service", JCacheableService.class); exceptionCache = ctx.getBean("exceptionCache", Cache.class); } @AfterEach void tearDown() { - if (ctx != null) { - ctx.close(); - } + ctx.close(); } @@ -87,8 +95,8 @@ class JCacheCustomInterceptorTests { @Test void customInterceptorAppliesWithCheckedException() { assertThatRuntimeException() - .isThrownBy(() -> cs.cacheWithCheckedException("id", true)) - .withCauseExactlyInstanceOf(IOException.class); + .isThrownBy(() -> cs.cacheWithCheckedException("id", true)) + .withCauseExactlyInstanceOf(IOException.class); } @@ -120,18 +128,28 @@ class JCacheCustomInterceptorTests { return new ConcurrentMapCache("exception"); } - @Bean - public JCacheInterceptor jCacheInterceptor(JCacheOperationSource cacheOperationSource) { - JCacheInterceptor cacheInterceptor = new TestCacheInterceptor(); - cacheInterceptor.setCacheOperationSource(cacheOperationSource); - return cacheInterceptor; - } } + static class CacheInterceptorBeanPostProcessor implements BeanPostProcessor { + + private final BeanFactory beanFactory; + + CacheInterceptorBeanPostProcessor(BeanFactory beanFactory) {this.beanFactory = beanFactory;} + + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + if (beanName.equals("jCacheInterceptor")) { + JCacheInterceptor cacheInterceptor = new TestCacheInterceptor(); + cacheInterceptor.setCacheOperationSource(beanFactory.getBean(JCacheOperationSource.class)); + return cacheInterceptor; + } + return bean; + } + + } + /** - * A test {@link org.springframework.cache.interceptor.CacheInterceptor} that handles special exception - * types. + * A test {@link JCacheInterceptor} that handles special exception types. */ @SuppressWarnings("serial") static class TestCacheInterceptor extends JCacheInterceptor { diff --git a/spring-context/src/test/java/org/springframework/cache/config/CustomInterceptorTests.java b/spring-context/src/test/java/org/springframework/cache/config/CustomInterceptorTests.java index c3a84002e58..9421d5a1cd5 100644 --- a/spring-context/src/test/java/org/springframework/cache/config/CustomInterceptorTests.java +++ b/spring-context/src/test/java/org/springframework/cache/config/CustomInterceptorTests.java @@ -23,6 +23,9 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.CacheInterceptor; @@ -40,6 +43,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; /** + * Tests that use a custom {@link CacheInterceptor}. + * * @author Stephane Nicoll */ class CustomInterceptorTests { @@ -50,7 +55,12 @@ class CustomInterceptorTests { @BeforeEach void setup() { - this.ctx = new AnnotationConfigApplicationContext(EnableCachingConfig.class); + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + context.getBeanFactory().addBeanPostProcessor( + new CacheInterceptorBeanPostProcessor(context.getBeanFactory())); + context.register(EnableCachingConfig.class); + context.refresh(); + this.ctx = context; this.cs = ctx.getBean("service", CacheableService.class); } @@ -59,6 +69,7 @@ class CustomInterceptorTests { this.ctx.close(); } + @Test void onlyOneInterceptorIsAvailable() { Map interceptors = this.ctx.getBeansOfType(CacheInterceptor.class); @@ -96,18 +107,28 @@ class CustomInterceptorTests { return new DefaultCacheableService(); } - @Bean - public CacheInterceptor cacheInterceptor(CacheOperationSource cacheOperationSource) { - CacheInterceptor cacheInterceptor = new TestCacheInterceptor(); - cacheInterceptor.setCacheManager(cacheManager()); - cacheInterceptor.setCacheOperationSources(cacheOperationSource); - return cacheInterceptor; + } + + static class CacheInterceptorBeanPostProcessor implements BeanPostProcessor { + + private final BeanFactory beanFactory; + + CacheInterceptorBeanPostProcessor(BeanFactory beanFactory) {this.beanFactory = beanFactory;} + + public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { + if (beanName.equals("cacheInterceptor")) { + CacheInterceptor cacheInterceptor = new TestCacheInterceptor(); + cacheInterceptor.setCacheManager(beanFactory.getBean(CacheManager.class)); + cacheInterceptor.setCacheOperationSource(beanFactory.getBean(CacheOperationSource.class)); + return cacheInterceptor; + } + return bean; } + } /** - * A test {@link CacheInterceptor} that handles special exception - * types. + * A test {@link CacheInterceptor} that handles special exception types. */ @SuppressWarnings("serial") static class TestCacheInterceptor extends CacheInterceptor { diff --git a/spring-context/src/test/java/org/springframework/context/annotation/BeanMethodPolymorphismTests.java b/spring-context/src/test/java/org/springframework/context/annotation/BeanMethodPolymorphismTests.java index 9a9ce4c6394..1b89d020bbc 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/BeanMethodPolymorphismTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/BeanMethodPolymorphismTests.java @@ -197,7 +197,10 @@ public class BeanMethodPolymorphismTests { */ @Test void beanMethodShadowing() { - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ShadowConfig.class); + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.setAllowBeanDefinitionOverriding(true); + ctx.register(ShadowConfig.class); + ctx.refresh(); assertThat(ctx.getBean(String.class)).isEqualTo("shadow"); } diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ClassPathBeanDefinitionScannerTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ClassPathBeanDefinitionScannerTests.java index dbc346cb315..329804f2aba 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/ClassPathBeanDefinitionScannerTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/ClassPathBeanDefinitionScannerTests.java @@ -194,6 +194,7 @@ class ClassPathBeanDefinitionScannerTests { @Test void testSimpleScanWithDefaultFiltersAndOverridingBean() { GenericApplicationContext context = new GenericApplicationContext(); + context.setAllowBeanDefinitionOverriding(true); context.registerBeanDefinition("stubFooDao", new RootBeanDefinition(TestBean.class)); ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context); scanner.setIncludeAnnotationConfig(false); diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java index c205ac781ab..ef810f56a5f 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java @@ -329,6 +329,7 @@ class ConfigurationClassPostProcessorTests { @Test void postProcessorOverridesNonApplicationBeanDefinitions() { + beanFactory.setAllowBeanDefinitionOverriding(true); RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class); rbd.setRole(RootBeanDefinition.ROLE_SUPPORT); beanFactory.registerBeanDefinition("bar", rbd); @@ -342,6 +343,7 @@ class ConfigurationClassPostProcessorTests { @Test void postProcessorDoesNotOverrideRegularBeanDefinitions() { + beanFactory.setAllowBeanDefinitionOverriding(true); RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class); rbd.setResource(new DescriptiveResource("XML or something")); beanFactory.registerBeanDefinition("bar", rbd); @@ -354,6 +356,7 @@ class ConfigurationClassPostProcessorTests { @Test void postProcessorDoesNotOverrideRegularBeanDefinitionsEvenWithScopedProxy() { + beanFactory.setAllowBeanDefinitionOverriding(true); RootBeanDefinition rbd = new RootBeanDefinition(TestBean.class); rbd.setResource(new DescriptiveResource("XML or something")); BeanDefinitionHolder proxied = ScopedProxyUtils.createScopedProxy( @@ -396,6 +399,7 @@ class ConfigurationClassPostProcessorTests { @Test void configurationClassesProcessedInCorrectOrder() { + beanFactory.setAllowBeanDefinitionOverriding(true); beanFactory.registerBeanDefinition("config1", new RootBeanDefinition(OverridingSingletonBeanConfig.class)); beanFactory.registerBeanDefinition("config2", new RootBeanDefinition(SingletonBeanConfig.class)); ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); @@ -410,6 +414,7 @@ class ConfigurationClassPostProcessorTests { @Test void configurationClassesWithValidOverridingForProgrammaticCall() { + beanFactory.setAllowBeanDefinitionOverriding(true); beanFactory.registerBeanDefinition("config1", new RootBeanDefinition(OverridingAgainSingletonBeanConfig.class)); beanFactory.registerBeanDefinition("config2", new RootBeanDefinition(OverridingSingletonBeanConfig.class)); beanFactory.registerBeanDefinition("config3", new RootBeanDefinition(SingletonBeanConfig.class)); @@ -425,6 +430,7 @@ class ConfigurationClassPostProcessorTests { @Test void configurationClassesWithInvalidOverridingForProgrammaticCall() { + beanFactory.setAllowBeanDefinitionOverriding(true); beanFactory.registerBeanDefinition("config1", new RootBeanDefinition(InvalidOverridingSingletonBeanConfig.class)); beanFactory.registerBeanDefinition("config2", new RootBeanDefinition(OverridingSingletonBeanConfig.class)); beanFactory.registerBeanDefinition("config3", new RootBeanDefinition(SingletonBeanConfig.class)); @@ -441,6 +447,7 @@ class ConfigurationClassPostProcessorTests { @Test // SPR-15384 void nestedConfigurationClassesProcessedInCorrectOrder() { + beanFactory.setAllowBeanDefinitionOverriding(true); beanFactory.registerBeanDefinition("config", new RootBeanDefinition(ConfigWithOrderedNestedClasses.class)); ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); pp.postProcessBeanFactory(beanFactory); @@ -454,6 +461,7 @@ class ConfigurationClassPostProcessorTests { @Test // SPR-16734 void innerConfigurationClassesProcessedInCorrectOrder() { + beanFactory.setAllowBeanDefinitionOverriding(true); beanFactory.registerBeanDefinition("config", new RootBeanDefinition(ConfigWithOrderedInnerClasses.class)); ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); pp.postProcessBeanFactory(beanFactory); diff --git a/spring-context/src/test/java/org/springframework/context/annotation/EnableAspectJAutoProxyTests.java b/spring-context/src/test/java/org/springframework/context/annotation/EnableAspectJAutoProxyTests.java index 261663e6164..953bb98e174 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/EnableAspectJAutoProxyTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/EnableAspectJAutoProxyTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 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. @@ -23,6 +23,7 @@ import example.scannable.FooDao; import example.scannable.FooService; import example.scannable.FooServiceImpl; import example.scannable.ServiceInvocationCounter; +import example.scannable.StubFooDao; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.junit.jupiter.api.Test; @@ -123,7 +124,7 @@ class EnableAspectJAutoProxyTests { } - @ComponentScan("example.scannable") + @Import({ ServiceInvocationCounter.class, StubFooDao.class }) @EnableAspectJAutoProxy(exposeProxy = true) static class ConfigWithExposedProxy { diff --git a/spring-context/src/test/java/org/springframework/context/annotation/NestedConfigurationClassTests.java b/spring-context/src/test/java/org/springframework/context/annotation/NestedConfigurationClassTests.java index 6e069c3a47b..f961a357715 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/NestedConfigurationClassTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/NestedConfigurationClassTests.java @@ -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. @@ -36,6 +36,7 @@ class NestedConfigurationClassTests { @Test void oneLevelDeep() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.setAllowBeanDefinitionOverriding(true); ctx.register(L0Config.L1Config.class); ctx.refresh(); @@ -55,6 +56,7 @@ class NestedConfigurationClassTests { @Test void twoLevelsDeep() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.setAllowBeanDefinitionOverriding(true); ctx.register(L0Config.class); ctx.refresh(); @@ -78,6 +80,7 @@ class NestedConfigurationClassTests { @Test void twoLevelsInLiteMode() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.setAllowBeanDefinitionOverriding(true); ctx.register(L0ConfigLight.class); ctx.refresh(); @@ -101,6 +104,7 @@ class NestedConfigurationClassTests { @Test void twoLevelsDeepWithInheritance() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.setAllowBeanDefinitionOverriding(true); ctx.register(S1Config.class); ctx.refresh(); @@ -130,6 +134,7 @@ class NestedConfigurationClassTests { @Test void twoLevelsDeepWithInheritanceThroughImport() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.setAllowBeanDefinitionOverriding(true); ctx.register(S1Importer.class); ctx.refresh(); @@ -159,6 +164,7 @@ class NestedConfigurationClassTests { @Test void twoLevelsDeepWithInheritanceAndScopedProxy() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.setAllowBeanDefinitionOverriding(true); ctx.register(S1ImporterWithProxy.class); ctx.refresh(); diff --git a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportAnnotationDetectionTests.java b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportAnnotationDetectionTests.java index 861754de3a0..5addfbee632 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportAnnotationDetectionTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportAnnotationDetectionTests.java @@ -65,6 +65,7 @@ public class ImportAnnotationDetectionTests { @Test void localImportIsProcessedLast() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.setAllowBeanDefinitionOverriding(true); ctx.register(MultiMetaImportConfigWithLocalImportWithBeanOverride.class); ctx.refresh(); assertThat(ctx.containsBean("testBean1")).isTrue(); diff --git a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportTests.java b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportTests.java index d44c74bb2ed..80172e53808 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ImportTests.java @@ -181,6 +181,7 @@ class ImportTests { @Test void testImportAnnotationWithMultipleArgumentsResultingInOverriddenBeanDefinition() { DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); + beanFactory.setAllowBeanDefinitionOverriding(true); beanFactory.registerBeanDefinition("config", new RootBeanDefinition( WithMultipleArgumentsThatWillCauseDuplication.class)); ConfigurationClassPostProcessor pp = new ConfigurationClassPostProcessor(); @@ -380,6 +381,7 @@ class ImportTests { @Test // gh-24643 void importedConfigOverridesScanned() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.setAllowBeanDefinitionOverriding(true); ctx.scan(SiblingImportingConfigA.class.getPackage().getName()); ctx.refresh(); diff --git a/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java b/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java index 1df89b1d03d..17c3f20883e 100644 --- a/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java +++ b/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java @@ -96,6 +96,7 @@ class EnableAsyncTests { @Test void properExceptionForExistingProxyDependencyMismatch() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.setAllowBeanDefinitionOverriding(true); ctx.register(AsyncConfig.class, AsyncBeanWithInterface.class, AsyncBeanUser.class); assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(ctx::refresh) .withCauseInstanceOf(BeanNotOfRequiredTypeException.class); @@ -105,6 +106,7 @@ class EnableAsyncTests { @Test void properExceptionForResolvedProxyDependencyMismatch() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.setAllowBeanDefinitionOverriding(true); ctx.register(AsyncConfig.class, AsyncBeanUser.class, AsyncBeanWithInterface.class); assertThatExceptionOfType(UnsatisfiedDependencyException.class).isThrownBy(ctx::refresh) .withCauseInstanceOf(BeanNotOfRequiredTypeException.class); diff --git a/spring-test/src/test/java/org/springframework/test/context/junit4/ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests.java b/spring-test/src/test/java/org/springframework/test/context/junit4/ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests.java index 2cc475b65cc..869664fe0b9 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit4/ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit4/ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 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. @@ -31,7 +31,7 @@ import org.springframework.util.ResourceUtils; * @see AbsolutePathSpringJUnit4ClassRunnerAppCtxTests * @see RelativePathSpringJUnit4ClassRunnerAppCtxTests */ -@ContextConfiguration(locations = { ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests.CLASSPATH_CONTEXT_RESOURCE_PATH }) +@ContextConfiguration(locations = { ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests.CLASSPATH_CONTEXT_RESOURCE_PATH }, inheritLocations = false) public class ClassPathResourceSpringJUnit4ClassRunnerAppCtxTests extends SpringJUnit4ClassRunnerAppCtxTests { /**