Revise singleton destruction for Bean Overrides
See gh-33678
This commit is contained in:
@@ -154,12 +154,6 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure we don't have any manually registered singletons registered, since we
|
||||
// register a bean override instance as a manual singleton at the end of this method.
|
||||
if (beanFactory.containsSingleton(beanName)) {
|
||||
destroySingleton(beanFactory, beanName);
|
||||
}
|
||||
|
||||
if (existingBeanDefinition != null) {
|
||||
// Validate the existing bean definition.
|
||||
//
|
||||
@@ -200,14 +194,19 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
|
||||
overrideMetadata.track(override, beanFactory);
|
||||
this.overrideRegistrar.registerNameForMetadata(overrideMetadata, beanName);
|
||||
|
||||
// Now we have an instance (the override) that we can register. At this stage, we don't
|
||||
// expect a singleton instance to be present. If for some reason a singleton instance
|
||||
// already exists, the following will throw an exception.
|
||||
// Now we have an instance (the override) that we can manually register as a singleton.
|
||||
//
|
||||
// However, we need to remove any existing singleton instance -- for example, a
|
||||
// manually registered singleton or a singleton that was registered as a side effect
|
||||
// of the isSingleton() check in validateBeanDefinition().
|
||||
//
|
||||
// As a bonus, by manually registering a singleton during "AOT processing", we allow
|
||||
// GenericApplicationContext's preDetermineBeanType() method to transparently register
|
||||
// runtime hints for a proxy generated by the above createOverride() invocation --
|
||||
// for example, when @MockitoBean creates a mock based on a JDK dynamic proxy.
|
||||
if (beanFactory.containsSingleton(beanName)) {
|
||||
destroySingleton(beanFactory, beanName);
|
||||
}
|
||||
beanFactory.registerSingleton(beanName, override);
|
||||
}
|
||||
|
||||
@@ -339,17 +338,14 @@ class BeanOverrideBeanFactoryPostProcessor implements BeanFactoryPostProcessor,
|
||||
private static void validateBeanDefinition(ConfigurableListableBeanFactory beanFactory, String beanName) {
|
||||
Assert.state(beanFactory.isSingleton(beanName),
|
||||
() -> "Unable to override bean '" + beanName + "': only singleton beans can be overridden.");
|
||||
|
||||
// Since the isSingleton() check above may have registered a singleton as a side
|
||||
// effect -- for example, for a FactoryBean -- we need to destroy the singleton,
|
||||
// because we later manually register a bean override instance as a singleton.
|
||||
destroySingleton(beanFactory, beanName);
|
||||
}
|
||||
|
||||
private static void destroySingleton(ConfigurableListableBeanFactory beanFactory, String beanName) {
|
||||
if (beanFactory instanceof DefaultListableBeanFactory dlbf) {
|
||||
dlbf.destroySingleton(beanName);
|
||||
if (!(beanFactory instanceof DefaultListableBeanFactory dlbf)) {
|
||||
throw new IllegalStateException("Cannot process bean override with a BeanFactory " +
|
||||
"that doesn't implement DefaultListableBeanFactory: " + beanFactory.getClass().getName());
|
||||
}
|
||||
dlbf.destroySingleton(beanName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user