From dd62224d2cb60c5621401141d01e4e5bb4cdac62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Mon, 25 Mar 2024 09:53:18 +0100 Subject: [PATCH] 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 --- .../support/DefaultListableBeanFactory.java | 64 ++++++++++++------- .../DefaultListableBeanFactoryTests.java | 6 ++ .../annotation/LookupAnnotationTests.java | 46 +++++++------ .../factory/xml/DuplicateBeanIdTests.java | 3 +- .../factory/xml/NestedBeansElementTests.java | 1 + .../config/JCacheCustomInterceptorTests.java | 46 +++++++++---- .../cache/config/CustomInterceptorTests.java | 39 ++++++++--- .../BeanMethodPolymorphismTests.java | 5 +- .../ClassPathBeanDefinitionScannerTests.java | 1 + .../ConfigurationClassPostProcessorTests.java | 8 +++ .../EnableAspectJAutoProxyTests.java | 5 +- .../NestedConfigurationClassTests.java | 8 ++- .../ImportAnnotationDetectionTests.java | 1 + .../annotation/configuration/ImportTests.java | 2 + .../annotation/EnableAsyncTests.java | 2 + ...rceSpringJUnit4ClassRunnerAppCtxTests.java | 4 +- 16 files changed, 170 insertions(+), 71 deletions(-) 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 32fecaa40da7..384c2cbc49a9 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 void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverridi * @since 4.1.2 */ public boolean isAllowBeanDefinitionOverriding() { - return this.allowBeanDefinitionOverriding; + return !Boolean.FALSE.equals(this.allowBeanDefinitionOverriding); } /** @@ -1142,27 +1143,8 @@ public void registerBeanDefinition(String beanName, BeanDefinition beanDefinitio 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 @@ else if (isConfigurationFrozen()) { } } + 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 a41a70e236b0..80fe11af2741 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 @@ void mergedBeanDefinitionChangesRetainedAfterFreezeConfiguration() { @Test void aliasCircle() { + lbf.setAllowBeanDefinitionOverriding(true); lbf.registerAlias("test", "test2"); lbf.registerAlias("test2", "test3"); @@ -867,6 +868,7 @@ void aliasChaining() { @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 @@ void beanDefinitionOverridingNotAllowed() { @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 @@ void beanDefinitionOverridingWithAlias() { @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 @@ void registerExistingSingletonWithAlreadyBound() { @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 @@ void expressionInStringArray() { @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 f12e9a0fac64..6c058db6ca7c 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 @@ */ 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 @@ void testWithoutConstructorArg() { @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 @@ void testWithOverloadedArg() { @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 @@ void testWithOneConstructorArg() { @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 @@ void testWithTwoConstructorArg() { @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 @@ void testWithThreeArgsShouldFail() { @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 @@ void testWithEarlyInjection() { 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 @@ public void testWithNullBean() { @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 @@ void testWithGenericBean() { @Test void testSingletonWithoutMetadataCaching() { + DefaultListableBeanFactory beanFactory = configureBeanFactory(); beanFactory.setCacheBeanMetadata(false); beanFactory.registerBeanDefinition("numberBean", new RootBeanDefinition(NumberBean.class)); @@ -140,6 +130,7 @@ void testSingletonWithoutMetadataCaching() { @Test void testPrototypeWithoutMetadataCaching() { + DefaultListableBeanFactory beanFactory = configureBeanFactory(); beanFactory.setCacheBeanMetadata(false); beanFactory.registerBeanDefinition("numberBean", new RootBeanDefinition(NumberBean.class, BeanDefinition.SCOPE_PROTOTYPE, null)); @@ -155,6 +146,23 @@ void testPrototypeWithoutMetadataCaching() { 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 7ee14248ae44..8544568823fe 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 @@ void duplicateBeanIdsWithinSameNestingLevelRaisesError() { @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 44cccf0b72fe..38e90b318107 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 @@ void getBean_withActiveProfile() { 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 27384ef73e5d..8cc2254b1554 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.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.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 @@ void customInterceptorAppliesWithRuntimeException() { @Test void customInterceptorAppliesWithCheckedException() { assertThatRuntimeException() - .isThrownBy(() -> cs.cacheWithCheckedException("id", true)) - .withCauseExactlyInstanceOf(IOException.class); + .isThrownBy(() -> cs.cacheWithCheckedException("id", true)) + .withCauseExactlyInstanceOf(IOException.class); } @@ -120,18 +128,28 @@ public Cache exceptionCache() { 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 c3a84002e588..9421d5a1cd5b 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.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.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 @@ void tearDown() { this.ctx.close(); } + @Test void onlyOneInterceptorIsAvailable() { Map interceptors = this.ctx.getBeansOfType(CacheInterceptor.class); @@ -96,18 +107,28 @@ public CacheableService service() { 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 9a9ce4c6394d..1b89d020bbc0 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 @@ void beanMethodOverloadingWithInheritanceAndList() { */ @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 dbc346cb315f..329804f2aba0 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 @@ void testSimpleScanWithDefaultFiltersAndNoPostProcessors() { @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 c205ac781ab9..ef810f56a5f5 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 @@ private void assertSupportForComposedAnnotationWithExclude(RootBeanDefinition be @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 @@ void postProcessorOverridesNonApplicationBeanDefinitions() { @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 @@ void postProcessorDoesNotOverrideRegularBeanDefinitions() { @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 @@ void detectAliasOverride() { @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 @@ void configurationClassesProcessedInCorrectOrder() { @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 @@ void configurationClassesWithValidOverridingForProgrammaticCall() { @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 @@ void configurationClassesWithInvalidOverridingForProgrammaticCall() { @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 @@ void nestedConfigurationClassesProcessedInCorrectOrder() { @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 261663e6164f..953bb98e1740 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.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 @@ static class ConfigWithCglibProxy { } - @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 6e069c3a47b2..f961a3577150 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 @@ void oneLevelDeep() { @Test void twoLevelsDeep() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.setAllowBeanDefinitionOverriding(true); ctx.register(L0Config.class); ctx.refresh(); @@ -78,6 +80,7 @@ void twoLevelsDeep() { @Test void twoLevelsInLiteMode() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.setAllowBeanDefinitionOverriding(true); ctx.register(L0ConfigLight.class); ctx.refresh(); @@ -101,6 +104,7 @@ void twoLevelsInLiteMode() { @Test void twoLevelsDeepWithInheritance() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.setAllowBeanDefinitionOverriding(true); ctx.register(S1Config.class); ctx.refresh(); @@ -130,6 +134,7 @@ void twoLevelsDeepWithInheritance() { @Test void twoLevelsDeepWithInheritanceThroughImport() { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.setAllowBeanDefinitionOverriding(true); ctx.register(S1Importer.class); ctx.refresh(); @@ -159,6 +164,7 @@ void twoLevelsDeepWithInheritanceThroughImport() { @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 861754de3a0d..5addfbee632d 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 @@ void localAndMetaImportsAreProcessed() { @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 d44c74bb2ede..80172e53808a 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 @@ void testImportAnnotationWithMultipleArguments() { @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 @@ void testProcessImports() { @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 1df89b1d03d0..17c3f20883ec 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 @@ void proxyingOccursWithMockitoStub() { @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 @@ void properExceptionForExistingProxyDependencyMismatch() { @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 2cc475b65cc2..869664fe0b9e 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 @@ * @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 { /**