Leniently tolerate late bean retrieval during destroySingletons()
Closes gh-22526 Closes gh-29730
This commit is contained in:
parent
138e7a0e07
commit
b5ca646431
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue