Backported core container concurrency refinements

Issue: SPR-16620
Issue: SPR-16625
Issue: SPR-16627
This commit is contained in:
Juergen Hoeller
2018-03-28 01:23:50 +02:00
parent 65a8aa1c09
commit 59189e5957
4 changed files with 68 additions and 39 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -908,12 +908,16 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
if (bw != null) {
return (FactoryBean<?>) bw.getWrappedInstance();
}
Object beanInstance = getSingleton(beanName, false);
if (beanInstance instanceof FactoryBean) {
return (FactoryBean<?>) beanInstance;
}
if (isSingletonCurrentlyInCreation(beanName) ||
(mbd.getFactoryBeanName() != null && isSingletonCurrentlyInCreation(mbd.getFactoryBeanName()))) {
return null;
}
Object instance = null;
Object instance;
try {
// Mark this bean as currently in creation, even if just partially.
beforeSingletonCreation(beanName);
@@ -1484,15 +1488,13 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
return;
}
if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
if (System.getSecurityManager() != null) {
if (bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
}
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) {
@@ -1628,7 +1630,6 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
@@ -1780,8 +1781,21 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
*/
@Override
protected void removeSingleton(String beanName) {
super.removeSingleton(beanName);
this.factoryBeanInstanceCache.remove(beanName);
synchronized (getSingletonMutex()) {
super.removeSingleton(beanName);
this.factoryBeanInstanceCache.remove(beanName);
}
}
/**
* Overridden to clear FactoryBean instance cache as well.
*/
@Override
protected void clearSingletonCache() {
synchronized (getSingletonMutex()) {
super.clearSingletonCache();
this.factoryBeanInstanceCache.clear();
}
}

View File

@@ -386,15 +386,8 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
* @see #registerDependentBean
*/
public void registerContainedBean(String containedBeanName, String containingBeanName) {
// A quick check for an existing entry upfront, avoiding synchronization...
Set<String> containedBeans = this.containedBeanMap.get(containingBeanName);
if (containedBeans != null && containedBeans.contains(containedBeanName)) {
return;
}
// No entry yet -> fully synchronized manipulation of the containedBeans Set
synchronized (this.containedBeanMap) {
containedBeans = this.containedBeanMap.get(containingBeanName);
Set<String> containedBeans = this.containedBeanMap.get(containingBeanName);
if (containedBeans == null) {
containedBeans = new LinkedHashSet<String>(8);
this.containedBeanMap.put(containingBeanName, containedBeans);
@@ -411,16 +404,10 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
* @param dependentBeanName the name of the dependent bean
*/
public void registerDependentBean(String beanName, String dependentBeanName) {
// A quick check for an existing entry upfront, avoiding synchronization...
String canonicalName = canonicalName(beanName);
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans != null && dependentBeans.contains(dependentBeanName)) {
return;
}
// No entry yet -> fully synchronized manipulation of the dependentBeans Set
synchronized (this.dependentBeanMap) {
dependentBeans = this.dependentBeanMap.get(canonicalName);
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
dependentBeans = new LinkedHashSet<String>(8);
this.dependentBeanMap.put(canonicalName, dependentBeans);
@@ -445,7 +432,9 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
* @since 4.0
*/
protected boolean isDependent(String beanName, String dependentBeanName) {
return isDependent(beanName, dependentBeanName, null);
synchronized (this.dependentBeanMap) {
return isDependent(beanName, dependentBeanName, null);
}
}
private boolean isDependent(String beanName, String dependentBeanName, Set<String> alreadySeen) {
@@ -490,7 +479,9 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
if (dependentBeans == null) {
return new String[0];
}
return StringUtils.toStringArray(dependentBeans);
synchronized (this.dependentBeanMap) {
return StringUtils.toStringArray(dependentBeans);
}
}
/**
@@ -504,7 +495,9 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
if (dependenciesForBean == null) {
return new String[0];
}
return StringUtils.toStringArray(dependenciesForBean);
synchronized (this.dependenciesForBeanMap) {
return StringUtils.toStringArray(dependenciesForBean);
}
}
public void destroySingletons() {
@@ -527,6 +520,14 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
clearSingletonCache();
}
/**
* Clear all cached singleton instances in this registry.
* @since 4.3.15
*/
protected void clearSingletonCache() {
synchronized (this.singletonObjects) {
this.singletonObjects.clear();
this.singletonFactories.clear();
@@ -562,7 +563,11 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
*/
protected void destroyBean(String beanName, DisposableBean bean) {
// Trigger destruction of dependent beans first...
Set<String> dependencies = this.dependentBeanMap.remove(beanName);
Set<String> dependencies;
synchronized (this.dependentBeanMap) {
// Within full synchronization in order to guarantee a disconnected Set
dependencies = this.dependentBeanMap.remove(beanName);
}
if (dependencies != null) {
if (logger.isDebugEnabled()) {
logger.debug("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
@@ -583,7 +588,11 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
}
// Trigger destruction of contained beans...
Set<String> containedBeans = this.containedBeanMap.remove(beanName);
Set<String> containedBeans;
synchronized (this.containedBeanMap) {
// Within full synchronization in order to guarantee a disconnected Set
containedBeans = this.containedBeanMap.remove(beanName);
}
if (containedBeans != null) {
for (String containedBeanName : containedBeans) {
destroySingleton(containedBeanName);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -117,7 +117,9 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
"Post-processing of FactoryBean's singleton object failed", ex);
}
}
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
}
}
return (object != NULL_OBJECT ? object : null);
@@ -218,17 +220,21 @@ public abstract class FactoryBeanRegistrySupport extends DefaultSingletonBeanReg
*/
@Override
protected void removeSingleton(String beanName) {
super.removeSingleton(beanName);
this.factoryBeanObjectCache.remove(beanName);
synchronized (getSingletonMutex()) {
super.removeSingleton(beanName);
this.factoryBeanObjectCache.remove(beanName);
}
}
/**
* Overridden to clear the FactoryBean object cache as well.
*/
@Override
public void destroySingletons() {
super.destroySingletons();
this.factoryBeanObjectCache.clear();
protected void clearSingletonCache() {
synchronized (getSingletonMutex()) {
super.clearSingletonCache();
this.factoryBeanObjectCache.clear();
}
}
/**