Invalidate cache entries for matching types after singleton creation

Closes gh-35239
This commit is contained in:
Juergen Hoeller
2025-07-25 22:38:57 +02:00
parent 5e338ef1b8
commit 8c44a61033
2 changed files with 34 additions and 4 deletions
@@ -1455,11 +1455,18 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
}
}
@Override
protected void addSingleton(String beanName, Object singletonObject) {
super.addSingleton(beanName, singletonObject);
Predicate<Class<?>> filter = (beanType -> beanType != Object.class && beanType.isInstance(singletonObject));
this.allBeanNamesByType.keySet().removeIf(filter);
this.singletonBeanNamesByType.keySet().removeIf(filter);
}
@Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
super.registerSingleton(beanName, singletonObject);
updateManualSingletonNames(set -> set.add(beanName), set -> !this.beanDefinitionMap.containsKey(beanName));
clearByTypeCache();
}
@Override
@@ -3202,6 +3202,29 @@ class DefaultListableBeanFactoryTests {
assertThat(holder.getNonPublicEnum()).isEqualTo(NonPublicEnum.VALUE_1);
}
@Test
void mostSpecificCacheEntryForTypeMatching() {
RootBeanDefinition bd1 = new RootBeanDefinition();
bd1.setFactoryBeanName("config");
bd1.setFactoryMethodName("create");
lbf.registerBeanDefinition("config", new RootBeanDefinition(BeanWithFactoryMethod.class));
lbf.registerBeanDefinition("bd1", bd1);
lbf.registerBeanDefinition("bd2", new RootBeanDefinition(NestedTestBean.class));
lbf.freezeConfiguration();
String[] allBeanNames = lbf.getBeanNamesForType(Object.class);
String[] nestedBeanNames = lbf.getBeanNamesForType(NestedTestBean.class);
assertThat(lbf.getType("bd1")).isEqualTo(TestBean.class);
assertThat(lbf.getBeanNamesForType(TestBean.class)).containsExactly("bd1");
assertThat(lbf.getBeanNamesForType(DerivedTestBean.class)).isEmpty();
lbf.getBean("bd1");
assertThat(lbf.getType("bd1")).isEqualTo(DerivedTestBean.class);
assertThat(lbf.getBeanNamesForType(TestBean.class)).containsExactly("bd1");
assertThat(lbf.getBeanNamesForType(DerivedTestBean.class)).containsExactly("bd1");
assertThat(lbf.getBeanNamesForType(NestedTestBean.class)).isSameAs(nestedBeanNames);
assertThat(lbf.getBeanNamesForType(Object.class)).isSameAs(allBeanNames);
}
private int registerBeanDefinitions(Properties p) {
return registerBeanDefinitions(p, null);
@@ -3418,7 +3441,7 @@ class DefaultListableBeanFactoryTests {
}
public TestBean create() {
TestBean tb = new TestBean();
DerivedTestBean tb = new DerivedTestBean();
tb.setName(this.name);
return tb;
}
@@ -3646,11 +3669,11 @@ class DefaultListableBeanFactoryTests {
private FactoryBean<?> factoryBean;
public final FactoryBean<?> getFactoryBean() {
public FactoryBean<?> getFactoryBean() {
return this.factoryBean;
}
public final void setFactoryBean(final FactoryBean<?> factoryBean) {
public void setFactoryBean(FactoryBean<?> factoryBean) {
this.factoryBean = factoryBean;
}
}