Backported core container concurrency refinements
Issue: SPR-16620 Issue: SPR-16625 Issue: SPR-16627
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user