@@ -155,7 +155,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
155155 private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver ();
156156
157157 /** Map from dependency type to corresponding autowired value */
158- private final Map <Class <?>, Object > resolvableDependencies = new HashMap <Class <?>, Object >(16 );
158+ private final Map <Class <?>, Object > resolvableDependencies = new ConcurrentHashMap <Class <?>, Object >(16 );
159159
160160 /** Map of bean definition objects, keyed by bean name */
161161 private final Map <String , BeanDefinition > beanDefinitionMap = new ConcurrentHashMap <String , BeanDefinition >(64 );
@@ -167,16 +167,16 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
167167 private final Map <Class <?>, String []> singletonBeanNamesByType = new ConcurrentHashMap <Class <?>, String []>(64 );
168168
169169 /** List of bean definition names, in registration order */
170- private final List <String > beanDefinitionNames = new ArrayList <String >(64 );
170+ private volatile List <String > beanDefinitionNames = new ArrayList <String >(64 );
171171
172172 /** List of names of manually registered singletons, in registration order */
173- private final Set <String > manualSingletonNames = new LinkedHashSet <String >(16 );
174-
175- /** Whether bean definition metadata may be cached for all beans */
176- private boolean configurationFrozen = false ;
173+ private volatile Set <String > manualSingletonNames = new LinkedHashSet <String >(16 );
177174
178175 /** Cached array of bean definition names in case of frozen configuration */
179- private String [] frozenBeanDefinitionNames ;
176+ private volatile String [] frozenBeanDefinitionNames ;
177+
178+ /** Whether bean definition metadata may be cached for all beans */
179+ private volatile boolean configurationFrozen = false ;
180180
181181
182182 /**
@@ -848,13 +848,32 @@ else if (!beanDefinition.equals(oldBeanDefinition)) {
848848 "] with [" + beanDefinition + "]" );
849849 }
850850 }
851+ this .beanDefinitionMap .put (beanName , beanDefinition );
851852 }
852853 else {
853- this .beanDefinitionNames .add (beanName );
854- this .manualSingletonNames .remove (beanName );
854+ if (hasBeanCreationStarted ()) {
855+ // Cannot modify startup-time collection elements anymore (for stable iteration)
856+ synchronized (this .beanDefinitionMap ) {
857+ this .beanDefinitionMap .put (beanName , beanDefinition );
858+ List <String > updatedDefinitions = new ArrayList <String >(this .beanDefinitionNames .size () + 1 );
859+ updatedDefinitions .addAll (this .beanDefinitionNames );
860+ updatedDefinitions .add (beanName );
861+ this .beanDefinitionNames = updatedDefinitions ;
862+ if (this .manualSingletonNames .contains (beanName )) {
863+ Set <String > updatedSingletons = new LinkedHashSet <String >(this .manualSingletonNames );
864+ updatedSingletons .remove (beanName );
865+ this .manualSingletonNames = updatedSingletons ;
866+ }
867+ }
868+ }
869+ else {
870+ // Still in startup registration phase
871+ this .beanDefinitionMap .put (beanName , beanDefinition );
872+ this .beanDefinitionNames .add (beanName );
873+ this .manualSingletonNames .remove (beanName );
874+ }
855875 this .frozenBeanDefinitionNames = null ;
856876 }
857- this .beanDefinitionMap .put (beanName , beanDefinition );
858877
859878 if (oldBeanDefinition != null || containsSingleton (beanName )) {
860879 resetBeanDefinition (beanName );
@@ -872,7 +891,19 @@ public void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionExc
872891 }
873892 throw new NoSuchBeanDefinitionException (beanName );
874893 }
875- this .beanDefinitionNames .remove (beanName );
894+
895+ if (hasBeanCreationStarted ()) {
896+ // Cannot modify startup-time collection elements anymore (for stable iteration)
897+ synchronized (this .beanDefinitionMap ) {
898+ List <String > updatedDefinitions = new ArrayList <String >(this .beanDefinitionNames );
899+ updatedDefinitions .remove (beanName );
900+ this .beanDefinitionNames = updatedDefinitions ;
901+ }
902+ }
903+ else {
904+ // Still in startup registration phase
905+ this .beanDefinitionNames .remove (beanName );
906+ }
876907 this .frozenBeanDefinitionNames = null ;
877908
878909 resetBeanDefinition (beanName );
@@ -914,9 +945,25 @@ protected boolean allowAliasOverriding() {
914945 @ Override
915946 public void registerSingleton (String beanName , Object singletonObject ) throws IllegalStateException {
916947 super .registerSingleton (beanName , singletonObject );
917- if (!this .beanDefinitionMap .containsKey (beanName )) {
918- this .manualSingletonNames .add (beanName );
948+
949+ if (hasBeanCreationStarted ()) {
950+ // Cannot modify startup-time collection elements anymore (for stable iteration)
951+ synchronized (this .beanDefinitionMap ) {
952+ if (!this .beanDefinitionMap .containsKey (beanName )) {
953+ Set <String > updatedSingletons = new LinkedHashSet <String >(this .manualSingletonNames .size () + 1 );
954+ updatedSingletons .addAll (this .manualSingletonNames );
955+ updatedSingletons .add (beanName );
956+ this .manualSingletonNames = updatedSingletons ;
957+ }
958+ }
919959 }
960+ else {
961+ // Still in startup registration phase
962+ if (!this .beanDefinitionMap .containsKey (beanName )) {
963+ this .manualSingletonNames .add (beanName );
964+ }
965+ }
966+
920967 clearByTypeCache ();
921968 }
922969
0 commit comments