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:
@@ -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<String, CacheInterceptor> 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 {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user