Consistently override (and prevent overriding for) aliases with bean definitions

Closes gh-27866
This commit is contained in:
Juergen Hoeller 2022-02-04 21:12:42 +01:00
parent e5af4aa608
commit 6b1c2dc944
3 changed files with 30 additions and 2 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2018 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -49,7 +49,7 @@ public class BeanDefinitionOverrideException extends BeanDefinitionStoreExceptio
super(beanDefinition.getResourceDescription(), beanName, super(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + existingDefinition + "] bound."); "' since there is already [" + existingDefinition + "] bound.");
this.beanDefinition = beanDefinition; this.beanDefinition = beanDefinition;
this.existingDefinition = existingDefinition; this.existingDefinition = existingDefinition;
} }

View File

@ -994,6 +994,23 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionMap.put(beanName, beanDefinition);
} }
else { else {
if (isAlias(beanName)) {
if (!isAllowBeanDefinitionOverriding()) {
String aliasedName = canonicalName(beanName);
if (containsBeanDefinition(aliasedName)) { // alias for existing bean definition
throw new BeanDefinitionOverrideException(
beanName, beanDefinition, getBeanDefinition(aliasedName));
}
else { // alias pointing to non-existing bean definition
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition for bean '" + beanName +
"' since there is already an alias for bean '" + aliasedName + "' bound.");
}
}
else {
removeAlias(beanName);
}
}
if (hasBeanCreationStarted()) { if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration) // Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) { synchronized (this.beanDefinitionMap) {

View File

@ -854,8 +854,11 @@ class DefaultListableBeanFactoryTests {
lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class)); lbf.registerBeanDefinition("test", new RootBeanDefinition(NestedTestBean.class));
lbf.registerAlias("otherTest", "test2"); lbf.registerAlias("otherTest", "test2");
lbf.registerAlias("test", "test2"); lbf.registerAlias("test", "test2");
lbf.registerAlias("test", "testX");
lbf.registerBeanDefinition("testX", new RootBeanDefinition(TestBean.class));
assertThat(lbf.getBean("test")).isInstanceOf(NestedTestBean.class); assertThat(lbf.getBean("test")).isInstanceOf(NestedTestBean.class);
assertThat(lbf.getBean("test2")).isInstanceOf(NestedTestBean.class); assertThat(lbf.getBean("test2")).isInstanceOf(NestedTestBean.class);
assertThat(lbf.getBean("testX")).isInstanceOf(TestBean.class);
} }
@Test @Test
@ -864,6 +867,7 @@ class DefaultListableBeanFactoryTests {
BeanDefinition oldDef = new RootBeanDefinition(TestBean.class); BeanDefinition oldDef = new RootBeanDefinition(TestBean.class);
BeanDefinition newDef = new RootBeanDefinition(NestedTestBean.class); BeanDefinition newDef = new RootBeanDefinition(NestedTestBean.class);
lbf.registerBeanDefinition("test", oldDef); lbf.registerBeanDefinition("test", oldDef);
lbf.registerAlias("test", "testX");
assertThatExceptionOfType(BeanDefinitionOverrideException.class).isThrownBy(() -> assertThatExceptionOfType(BeanDefinitionOverrideException.class).isThrownBy(() ->
lbf.registerBeanDefinition("test", newDef)) lbf.registerBeanDefinition("test", newDef))
.satisfies(ex -> { .satisfies(ex -> {
@ -871,6 +875,13 @@ class DefaultListableBeanFactoryTests {
assertThat(ex.getBeanDefinition()).isEqualTo(newDef); assertThat(ex.getBeanDefinition()).isEqualTo(newDef);
assertThat(ex.getExistingDefinition()).isEqualTo(oldDef); assertThat(ex.getExistingDefinition()).isEqualTo(oldDef);
}); });
assertThatExceptionOfType(BeanDefinitionOverrideException.class).isThrownBy(() ->
lbf.registerBeanDefinition("testX", newDef))
.satisfies(ex -> {
assertThat(ex.getBeanName()).isEqualTo("testX");
assertThat(ex.getBeanDefinition()).isEqualTo(newDef);
assertThat(ex.getExistingDefinition()).isEqualTo(oldDef);
});
} }
@Test @Test