From 755721fd216bb3dc77d62e553038cc7bda1ea25b Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 31 Aug 2020 18:00:51 +0200 Subject: [PATCH] Avoid full singleton lock for getSingleton(beanName, false) Closes gh-25667 (cherry picked from commit d8c420ab756beff8c4490cdb4dd05ed4dbfcf2c4) --- .../support/DefaultSingletonBeanRegistry.java | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java index 63eb72954ac..0a81aef4e9f 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java +++ b/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> singletonFactories = new HashMap<>(16); /** Cache of early singleton objects: bean name to bean instance. */ - private final Map earlySingletonObjects = new HashMap<>(16); + private final Map earlySingletonObjects = new ConcurrentHashMap<>(16); /** Set of registered singletons, containing the bean names in registration order. */ private final Set registeredSingletons = new LinkedHashSet<>(256); @@ -178,16 +178,24 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements */ @Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { + // Quick check for existing instance without full singleton lock Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { - synchronized (this.singletonObjects) { - singletonObject = this.earlySingletonObjects.get(beanName); - if (singletonObject == null && allowEarlyReference) { - ObjectFactory singletonFactory = this.singletonFactories.get(beanName); - if (singletonFactory != null) { - singletonObject = singletonFactory.getObject(); - this.earlySingletonObjects.put(beanName, singletonObject); - this.singletonFactories.remove(beanName); + singletonObject = this.earlySingletonObjects.get(beanName); + if (singletonObject == null && allowEarlyReference) { + synchronized (this.singletonObjects) { + // Consistent creation of early reference within full singleton lock + singletonObject = this.singletonObjects.get(beanName); + if (singletonObject == null) { + singletonObject = this.earlySingletonObjects.get(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); + } + } } } }