Leniently tolerate late bean retrieval during destroySingletons()

Closes gh-22526
Closes gh-29730
This commit is contained in:
Juergen Hoeller 2024-03-04 17:21:02 +01:00
parent 138e7a0e07
commit b5ca646431
2 changed files with 22 additions and 22 deletions

View File

@ -99,13 +99,13 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
@Nullable
private volatile Thread singletonCreationThread;
/** Flag that indicates whether we're currently within destroySingletons. */
private volatile boolean singletonsCurrentlyInDestruction = false;
/** Collection of suppressed Exceptions, available for associating related causes. */
@Nullable
private Set<Exception> suppressedExceptions;
/** Flag that indicates whether we're currently within destroySingletons. */
private boolean singletonsCurrentlyInDestruction = false;
/** Disposable bean instances: bean name to disposable instance. */
private final Map<String, DisposableBean> disposableBeans = new LinkedHashMap<>();
@ -562,13 +562,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
if (logger.isTraceEnabled()) {
logger.trace("Destroying singletons in " + this);
}
this.singletonLock.lock();
try {
this.singletonsCurrentlyInDestruction = true;
}
finally {
this.singletonLock.unlock();
}
this.singletonsCurrentlyInDestruction = true;
String[] disposableBeanNames;
synchronized (this.disposableBeans) {
@ -610,21 +604,28 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
* @see #destroyBean
*/
public void destroySingleton(String beanName) {
// Remove a registered singleton of the given name, if any.
this.singletonLock.lock();
try {
removeSingleton(beanName);
}
finally {
this.singletonLock.unlock();
}
// Destroy the corresponding DisposableBean instance.
// This also triggers the destruction of dependent beans.
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
disposableBean = this.disposableBeans.remove(beanName);
}
destroyBean(beanName, disposableBean);
// destroySingletons() removes all singleton instances at the end,
// leniently tolerating late retrieval during the shutdown phase.
if (!this.singletonsCurrentlyInDestruction) {
// For an individual destruction, remove the registered instance now.
// As of 6.2, this happens after the current bean's destruction step,
// allowing for late bean retrieval by on-demand suppliers etc.
this.singletonLock.lock();
try {
removeSingleton(beanName);
}
finally {
this.singletonLock.unlock();
}
}
}
/**

View File

@ -85,12 +85,11 @@ public class Service implements ApplicationContextAware, MessageSourceAware, Dis
Assert.state(applicationContext.getBean("messageSource") instanceof StaticMessageSource,
"Invalid MessageSource bean");
try {
// Should not throw BeanCreationNotAllowedException on 6.2 anymore
applicationContext.getBean("service2");
// Should have thrown BeanCreationNotAllowedException
properlyDestroyed = false;
}
catch (BeanCreationNotAllowedException ex) {
// expected
properlyDestroyed = false;
}
});
thread.start();