diff --git a/build.gradle b/build.gradle index 46e010e1748..6b45d6e399b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,11 +1,11 @@ plugins { id 'io.spring.dependency-management' version '1.0.9.RELEASE' apply false + id 'io.spring.nohttp' version '0.0.5.RELEASE' id 'org.jetbrains.kotlin.jvm' version '1.4.0' apply false id 'org.jetbrains.dokka' version '0.10.1' apply false id 'org.asciidoctor.jvm.convert' version '2.4.0' - id 'io.spring.nohttp' version '0.0.5.RELEASE' - id 'de.undercouch.download' version '4.0.4' - id "io.freefair.aspectj" version '5.0.0' apply false + id 'de.undercouch.download' version '4.1.1' + id "io.freefair.aspectj" version '5.1.1' apply false id "com.github.ben-manes.versions" version '0.28.0' id "me.champeau.gradle.jmh" version "0.5.0" apply false } 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); + } + } } } }