Skip to content

Commit d9ab6aa

Browse files
committed
Revised RootBeanDefinition's externallyManaged* Sets to rely on postProcessingLock
This allows us to avoid early initialization of footprint-heavy ConcurrentHashMaps, and reuses the existing postProcessingLock which will typically be active already when registerExternallyManaged* calls come in from the bean factory's post-processing phase. Issue: SPR-11343 (cherry picked from commit a599b57)
1 parent aa1babd commit d9ab6aa

File tree

2 files changed

+57
-30
lines changed

2 files changed

+57
-30
lines changed

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.beans.factory.support;
1818

1919
import org.springframework.beans.MutablePropertyValues;
20+
import org.springframework.beans.factory.config.BeanDefinition;
2021
import org.springframework.beans.factory.config.ConstructorArgumentValues;
2122
import org.springframework.util.ObjectUtils;
2223

@@ -127,7 +128,7 @@ public ChildBeanDefinition(
127128
* @param original the original bean definition to copy from
128129
*/
129130
public ChildBeanDefinition(ChildBeanDefinition original) {
130-
super(original);
131+
super((BeanDefinition) original);
131132
}
132133

133134

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

+55-29
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818

1919
import java.lang.reflect.Member;
2020
import java.lang.reflect.Method;
21-
import java.util.Map;
22-
import java.util.concurrent.ConcurrentHashMap;
21+
import java.util.HashSet;
22+
import java.util.Set;
2323

2424
import org.springframework.beans.MutablePropertyValues;
2525
import org.springframework.beans.factory.config.BeanDefinition;
@@ -48,19 +48,10 @@
4848
@SuppressWarnings("serial")
4949
public class RootBeanDefinition extends AbstractBeanDefinition {
5050

51-
// using a ConcurrentHashMap as a Set
52-
private final Map<Member, Boolean> externallyManagedConfigMembers = new ConcurrentHashMap<Member, Boolean>(0);
53-
54-
// using a ConcurrentHashMap as a Set
55-
private final Map<String, Boolean> externallyManagedInitMethods = new ConcurrentHashMap<String, Boolean>(0);
56-
57-
// using a ConcurrentHashMap as a Set
58-
private final Map<String, Boolean> externallyManagedDestroyMethods = new ConcurrentHashMap<String, Boolean>(0);
51+
boolean allowCaching = true;
5952

6053
private BeanDefinitionHolder decoratedDefinition;
6154

62-
boolean allowCaching = true;
63-
6455
private volatile Class<?> targetType;
6556

6657
boolean isFactoryMethodUnique = false;
@@ -87,6 +78,12 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
8778
/** Package-visible field that indicates a before-instantiation post-processor having kicked in */
8879
volatile Boolean beforeInstantiationResolved;
8980

81+
private Set<Member> externallyManagedConfigMembers;
82+
83+
private Set<String> externallyManagedInitMethods;
84+
85+
private Set<String> externallyManagedDestroyMethods;
86+
9087

9188
/**
9289
* Create a new RootBeanDefinition, to be configured through its bean
@@ -225,9 +222,9 @@ public RootBeanDefinition(String beanClassName, ConstructorArgumentValues cargs,
225222
* @param original the original bean definition to copy from
226223
*/
227224
public RootBeanDefinition(RootBeanDefinition original) {
228-
super(original);
229-
this.decoratedDefinition = original.decoratedDefinition;
225+
super((BeanDefinition) original);
230226
this.allowCaching = original.allowCaching;
227+
this.decoratedDefinition = original.decoratedDefinition;
231228
this.targetType = original.targetType;
232229
this.isFactoryMethodUnique = original.isFactoryMethodUnique;
233230
}
@@ -252,6 +249,20 @@ public void setParentName(String parentName) {
252249
}
253250
}
254251

252+
/**
253+
* Register a target definition that is being decorated by this bean definition.
254+
*/
255+
public void setDecoratedDefinition(BeanDefinitionHolder decoratedDefinition) {
256+
this.decoratedDefinition = decoratedDefinition;
257+
}
258+
259+
/**
260+
* Return the target definition that is being decorated by this bean definition, if any.
261+
*/
262+
public BeanDefinitionHolder getDecoratedDefinition() {
263+
return this.decoratedDefinition;
264+
}
265+
255266
/**
256267
* Specify the target type of this bean definition, if known in advance.
257268
*/
@@ -294,37 +305,52 @@ public Method getResolvedFactoryMethod() {
294305
}
295306
}
296307

297-
298308
public void registerExternallyManagedConfigMember(Member configMember) {
299-
this.externallyManagedConfigMembers.put(configMember, Boolean.TRUE);
309+
synchronized (this.postProcessingLock) {
310+
if (this.externallyManagedConfigMembers == null) {
311+
this.externallyManagedConfigMembers = new HashSet<Member>(1);
312+
}
313+
this.externallyManagedConfigMembers.add(configMember);
314+
}
300315
}
301316

302317
public boolean isExternallyManagedConfigMember(Member configMember) {
303-
return this.externallyManagedConfigMembers.containsKey(configMember);
318+
synchronized (this.postProcessingLock) {
319+
return (this.externallyManagedConfigMembers != null &&
320+
this.externallyManagedConfigMembers.contains(configMember));
321+
}
304322
}
305323

306324
public void registerExternallyManagedInitMethod(String initMethod) {
307-
this.externallyManagedInitMethods.put(initMethod, Boolean.TRUE);
325+
synchronized (this.postProcessingLock) {
326+
if (this.externallyManagedInitMethods == null) {
327+
this.externallyManagedInitMethods = new HashSet<String>(1);
328+
}
329+
this.externallyManagedInitMethods.add(initMethod);
330+
}
308331
}
309332

310333
public boolean isExternallyManagedInitMethod(String initMethod) {
311-
return this.externallyManagedInitMethods.containsKey(initMethod);
334+
synchronized (this.postProcessingLock) {
335+
return (this.externallyManagedInitMethods != null &&
336+
this.externallyManagedInitMethods.contains(initMethod));
337+
}
312338
}
313339

314340
public void registerExternallyManagedDestroyMethod(String destroyMethod) {
315-
this.externallyManagedDestroyMethods.put(destroyMethod, Boolean.TRUE);
341+
synchronized (this.postProcessingLock) {
342+
if (this.externallyManagedDestroyMethods == null) {
343+
this.externallyManagedDestroyMethods = new HashSet<String>(1);
344+
}
345+
this.externallyManagedDestroyMethods.add(destroyMethod);
346+
}
316347
}
317348

318349
public boolean isExternallyManagedDestroyMethod(String destroyMethod) {
319-
return this.externallyManagedDestroyMethods.containsKey(destroyMethod);
320-
}
321-
322-
public void setDecoratedDefinition(BeanDefinitionHolder decoratedDefinition) {
323-
this.decoratedDefinition = decoratedDefinition;
324-
}
325-
326-
public BeanDefinitionHolder getDecoratedDefinition() {
327-
return this.decoratedDefinition;
350+
synchronized (this.postProcessingLock) {
351+
return (this.externallyManagedDestroyMethods != null &&
352+
this.externallyManagedDestroyMethods.contains(destroyMethod));
353+
}
328354
}
329355

330356

0 commit comments

Comments
 (0)