Browse Source

Avoid full singleton lock for getSingleton(beanName, false)

Closes gh-25667

(cherry picked from commit d8c420ab75)
pull/23967/head
Juergen Hoeller 6 years ago
parent
commit
755721fd21
  1. 26
      spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java

26
spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java

@ -81,7 +81,7 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */ /** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
/** Set of registered singletons, containing the bean names in registration order. */ /** Set of registered singletons, containing the bean names in registration order. */
private final Set<String> registeredSingletons = new LinkedHashSet<>(256); private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
@ -178,16 +178,24 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
*/ */
@Nullable @Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) { protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName); Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName);
singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) {
if (singletonObject == null && allowEarlyReference) { synchronized (this.singletonObjects) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); // Consistent creation of early reference within full singleton lock
if (singletonFactory != null) { singletonObject = this.singletonObjects.get(beanName);
singletonObject = singletonFactory.getObject(); if (singletonObject == null) {
this.earlySingletonObjects.put(beanName, singletonObject); singletonObject = this.earlySingletonObjects.get(beanName);
this.singletonFactories.remove(beanName); if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
} }
} }
} }

Loading…
Cancel
Save