Browse Source

Invalidate cache entries for matching types after singleton creation

Closes gh-35239
pull/35405/head
Juergen Hoeller 5 months ago
parent
commit
8c44a61033
  1. 9
      spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
  2. 29
      spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java

9
spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java

@ -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 @Override
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
super.registerSingleton(beanName, singletonObject); super.registerSingleton(beanName, singletonObject);
updateManualSingletonNames(set -> set.add(beanName), set -> !this.beanDefinitionMap.containsKey(beanName)); updateManualSingletonNames(set -> set.add(beanName), set -> !this.beanDefinitionMap.containsKey(beanName));
clearByTypeCache();
} }
@Override @Override

29
spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java

@ -3202,6 +3202,29 @@ class DefaultListableBeanFactoryTests {
assertThat(holder.getNonPublicEnum()).isEqualTo(NonPublicEnum.VALUE_1); 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) { private int registerBeanDefinitions(Properties p) {
return registerBeanDefinitions(p, null); return registerBeanDefinitions(p, null);
@ -3418,7 +3441,7 @@ class DefaultListableBeanFactoryTests {
} }
public TestBean create() { public TestBean create() {
TestBean tb = new TestBean(); DerivedTestBean tb = new DerivedTestBean();
tb.setName(this.name); tb.setName(this.name);
return tb; return tb;
} }
@ -3646,11 +3669,11 @@ class DefaultListableBeanFactoryTests {
private FactoryBean<?> factoryBean; private FactoryBean<?> factoryBean;
public final FactoryBean<?> getFactoryBean() { public FactoryBean<?> getFactoryBean() {
return this.factoryBean; return this.factoryBean;
} }
public final void setFactoryBean(final FactoryBean<?> factoryBean) { public void setFactoryBean(FactoryBean<?> factoryBean) {
this.factoryBean = factoryBean; this.factoryBean = factoryBean;
} }
} }

Loading…
Cancel
Save