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
|
@Nullable
|
||||||
private volatile Thread singletonCreationThread;
|
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. */
|
/** Collection of suppressed Exceptions, available for associating related causes. */
|
||||||
@Nullable
|
@Nullable
|
||||||
private Set<Exception> suppressedExceptions;
|
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. */
|
/** Disposable bean instances: bean name to disposable instance. */
|
||||||
private final Map<String, DisposableBean> disposableBeans = new LinkedHashMap<>();
|
private final Map<String, DisposableBean> disposableBeans = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
@ -562,13 +562,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace("Destroying singletons in " + this);
|
logger.trace("Destroying singletons in " + this);
|
||||||
}
|
}
|
||||||
this.singletonLock.lock();
|
this.singletonsCurrentlyInDestruction = true;
|
||||||
try {
|
|
||||||
this.singletonsCurrentlyInDestruction = true;
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
this.singletonLock.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] disposableBeanNames;
|
String[] disposableBeanNames;
|
||||||
synchronized (this.disposableBeans) {
|
synchronized (this.disposableBeans) {
|
||||||
|
@ -610,21 +604,28 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
||||||
* @see #destroyBean
|
* @see #destroyBean
|
||||||
*/
|
*/
|
||||||
public void destroySingleton(String beanName) {
|
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.
|
// Destroy the corresponding DisposableBean instance.
|
||||||
|
// This also triggers the destruction of dependent beans.
|
||||||
DisposableBean disposableBean;
|
DisposableBean disposableBean;
|
||||||
synchronized (this.disposableBeans) {
|
synchronized (this.disposableBeans) {
|
||||||
disposableBean = this.disposableBeans.remove(beanName);
|
disposableBean = this.disposableBeans.remove(beanName);
|
||||||
}
|
}
|
||||||
destroyBean(beanName, disposableBean);
|
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,
|
Assert.state(applicationContext.getBean("messageSource") instanceof StaticMessageSource,
|
||||||
"Invalid MessageSource bean");
|
"Invalid MessageSource bean");
|
||||||
try {
|
try {
|
||||||
|
// Should not throw BeanCreationNotAllowedException on 6.2 anymore
|
||||||
applicationContext.getBean("service2");
|
applicationContext.getBean("service2");
|
||||||
// Should have thrown BeanCreationNotAllowedException
|
|
||||||
properlyDestroyed = false;
|
|
||||||
}
|
}
|
||||||
catch (BeanCreationNotAllowedException ex) {
|
catch (BeanCreationNotAllowedException ex) {
|
||||||
// expected
|
properlyDestroyed = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
thread.start();
|
thread.start();
|
||||||
|
|
Loading…
Reference in New Issue