Ensure bean definitions can be removed concurrently

Prior to this commit, concurrent invocations of
DefaultListableBeanFactory.removeBeanDefinition() could result in a
NullPointerException.

This commit fixes this by adding an appropriate not-null check in
resetBeanDefinition().

Closes gh-23542
This commit is contained in:
Sam Brannen
2019-09-17 12:59:37 +02:00
parent ca2b2f5533
commit b2aad1c3b1
2 changed files with 30 additions and 1 deletions

View File

@@ -38,6 +38,7 @@ import java.util.Properties;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Priority;
import javax.security.auth.Subject;
@@ -817,6 +818,32 @@ public class DefaultListableBeanFactoryTests {
assertTrue(lbf.getBean("test2") instanceof NestedTestBean);
}
@Test // gh-23542
public void concurrentBeanDefinitionRemoval() {
final int MAX = 200;
lbf.setAllowBeanDefinitionOverriding(false);
// Register the bean definitions before invoking preInstantiateSingletons()
// to simulate realistic usage of an ApplicationContext; otherwise, the bean
// factory thinks it's an "empty" factory which causes this test to fail in
// an unrealistic manner.
IntStream.range(0, MAX).forEach(this::registerTestBean);
lbf.preInstantiateSingletons();
// This test is considered successful if the following does not result in an exception.
IntStream.range(0, MAX).parallel().forEach(this::removeTestBean);
}
private void registerTestBean(int i) {
String name = "test" + i;
lbf.registerBeanDefinition(name, new RootBeanDefinition(TestBean.class));
}
private void removeTestBean(int i) {
String name = "test" + i;
lbf.removeBeanDefinition(name);
}
@Test
public void testBeanDefinitionOverridingNotAllowed() {
lbf.setAllowBeanDefinitionOverriding(false);