Skip to content

Commit b5cedd4

Browse files
committed
Consistent and efficient access to BeanDefinition argument values
Issue: SPR-16192
1 parent e2bb06e commit b5cedd4

File tree

13 files changed

+195
-116
lines changed

13 files changed

+195
-116
lines changed

spring-beans/src/main/java/org/springframework/beans/MutablePropertyValues.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ public boolean isEmpty() {
318318
*/
319319
public void registerProcessedProperty(String propertyName) {
320320
if (this.processedProperties == null) {
321-
this.processedProperties = new HashSet<>();
321+
this.processedProperties = new HashSet<>(4);
322322
}
323323
this.processedProperties.add(propertyName);
324324
}

spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinition.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,13 +219,29 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
219219
*/
220220
ConstructorArgumentValues getConstructorArgumentValues();
221221

222+
/**
223+
* Return if there are constructor argument values defined for this bean.
224+
* @since 5.0.2
225+
*/
226+
default boolean hasConstructorArgumentValues() {
227+
return !getConstructorArgumentValues().isEmpty();
228+
}
229+
222230
/**
223231
* Return the property values to be applied to a new instance of the bean.
224232
* <p>The returned instance can be modified during bean factory post-processing.
225233
* @return the MutablePropertyValues object (never {@code null})
226234
*/
227235
MutablePropertyValues getPropertyValues();
228236

237+
/**
238+
* Return if there are property values values defined for this bean.
239+
* @since 5.0.2
240+
*/
241+
default boolean hasPropertyValues() {
242+
return !getPropertyValues().isEmpty();
243+
}
244+
229245

230246
// Read-only attributes
231247

spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinitionVisitor.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,14 @@ public void visitBeanDefinition(BeanDefinition beanDefinition) {
8181
visitFactoryBeanName(beanDefinition);
8282
visitFactoryMethodName(beanDefinition);
8383
visitScope(beanDefinition);
84-
visitPropertyValues(beanDefinition.getPropertyValues());
85-
ConstructorArgumentValues cas = beanDefinition.getConstructorArgumentValues();
86-
visitIndexedArgumentValues(cas.getIndexedArgumentValues());
87-
visitGenericArgumentValues(cas.getGenericArgumentValues());
84+
if (beanDefinition.hasPropertyValues()) {
85+
visitPropertyValues(beanDefinition.getPropertyValues());
86+
}
87+
if (beanDefinition.hasConstructorArgumentValues()) {
88+
ConstructorArgumentValues cas = beanDefinition.getConstructorArgumentValues();
89+
visitIndexedArgumentValues(cas.getIndexedArgumentValues());
90+
visitGenericArgumentValues(cas.getGenericArgumentValues());
91+
}
8892
}
8993

9094
protected void visitParentName(BeanDefinition beanDefinition) {

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -723,7 +723,8 @@ protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition m
723723
// Can't clearly figure out exact method due to type converting / autowiring!
724724
Class<?> commonType = null;
725725
Method uniqueCandidate = null;
726-
int minNrOfArgs = mbd.getConstructorArgumentValues().getArgumentCount();
726+
int minNrOfArgs =
727+
(mbd.hasConstructorArgumentValues() ? mbd.getConstructorArgumentValues().getArgumentCount() : 0);
727728
Method[] candidates = ReflectionUtils.getUniqueDeclaredMethods(factoryClass);
728729
for (Method factoryMethod : candidates) {
729730
if (Modifier.isStatic(factoryMethod.getModifiers()) == isStatic &&
@@ -1277,10 +1278,8 @@ protected BeanWrapper autowireConstructor(
12771278
* @param bw BeanWrapper with bean instance
12781279
*/
12791280
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
1280-
PropertyValues pvs = mbd.getPropertyValues();
1281-
12821281
if (bw == null) {
1283-
if (!pvs.isEmpty()) {
1282+
if (mbd.hasPropertyValues()) {
12841283
throw new BeanCreationException(
12851284
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
12861285
}
@@ -1311,6 +1310,8 @@ protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable B
13111310
return;
13121311
}
13131312

1313+
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
1314+
13141315
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
13151316
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
13161317
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
@@ -1332,6 +1333,9 @@ protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable B
13321333
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
13331334

13341335
if (hasInstAwareBpps || needsDepCheck) {
1336+
if (pvs == null) {
1337+
pvs = mbd.getPropertyValues();
1338+
}
13351339
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
13361340
if (hasInstAwareBpps) {
13371341
for (BeanPostProcessor bp : getBeanPostProcessors()) {
@@ -1349,7 +1353,9 @@ protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable B
13491353
}
13501354
}
13511355

1352-
applyPropertyValues(beanName, mbd, bw, pvs);
1356+
if (pvs != null) {
1357+
applyPropertyValues(beanName, mbd, bw, pvs);
1358+
}
13531359
}
13541360

13551361
/**

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

Lines changed: 63 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,14 @@ public abstract class AbstractBeanDefinition extends BeanMetadataAttributeAccess
173173
@Nullable
174174
private String factoryMethodName;
175175

176+
@Nullable
176177
private ConstructorArgumentValues constructorArgumentValues;
177178

179+
@Nullable
178180
private MutablePropertyValues propertyValues;
179181

180-
private MethodOverrides methodOverrides = new MethodOverrides();
182+
@Nullable
183+
private MethodOverrides methodOverrides;
181184

182185
@Nullable
183186
private String initMethodName;
@@ -212,8 +215,8 @@ protected AbstractBeanDefinition() {
212215
* constructor argument values and property values.
213216
*/
214217
protected AbstractBeanDefinition(@Nullable ConstructorArgumentValues cargs, @Nullable MutablePropertyValues pvs) {
215-
this.constructorArgumentValues = (cargs != null ? cargs : new ConstructorArgumentValues());
216-
this.propertyValues = (pvs != null ? pvs : new MutablePropertyValues());
218+
this.constructorArgumentValues = cargs;
219+
this.propertyValues = pvs;
217220
}
218221

219222
/**
@@ -229,8 +232,6 @@ protected AbstractBeanDefinition(BeanDefinition original) {
229232
setLazyInit(original.isLazyInit());
230233
setFactoryBeanName(original.getFactoryBeanName());
231234
setFactoryMethodName(original.getFactoryMethodName());
232-
this.constructorArgumentValues = new ConstructorArgumentValues(original.getConstructorArgumentValues());
233-
this.propertyValues = new MutablePropertyValues(original.getPropertyValues());
234235
setRole(original.getRole());
235236
setSource(original.getSource());
236237
copyAttributesFrom(original);
@@ -240,6 +241,15 @@ protected AbstractBeanDefinition(BeanDefinition original) {
240241
if (originalAbd.hasBeanClass()) {
241242
setBeanClass(originalAbd.getBeanClass());
242243
}
244+
if (originalAbd.hasConstructorArgumentValues()) {
245+
setConstructorArgumentValues(new ConstructorArgumentValues(original.getConstructorArgumentValues()));
246+
}
247+
if (originalAbd.hasPropertyValues()) {
248+
setPropertyValues(new MutablePropertyValues(original.getPropertyValues()));
249+
}
250+
if (originalAbd.hasMethodOverrides()) {
251+
setMethodOverrides(new MethodOverrides(originalAbd.getMethodOverrides()));
252+
}
243253
setAutowireMode(originalAbd.getAutowireMode());
244254
setDependencyCheck(originalAbd.getDependencyCheck());
245255
setDependsOn(originalAbd.getDependsOn());
@@ -249,7 +259,6 @@ protected AbstractBeanDefinition(BeanDefinition original) {
249259
setInstanceSupplier(originalAbd.getInstanceSupplier());
250260
setNonPublicAccessAllowed(originalAbd.isNonPublicAccessAllowed());
251261
setLenientConstructorResolution(originalAbd.isLenientConstructorResolution());
252-
setMethodOverrides(new MethodOverrides(originalAbd.getMethodOverrides()));
253262
setInitMethodName(originalAbd.getInitMethodName());
254263
setEnforceInitMethod(originalAbd.isEnforceInitMethod());
255264
setDestroyMethodName(originalAbd.getDestroyMethodName());
@@ -258,6 +267,8 @@ protected AbstractBeanDefinition(BeanDefinition original) {
258267
setResource(originalAbd.getResource());
259268
}
260269
else {
270+
setConstructorArgumentValues(new ConstructorArgumentValues(original.getConstructorArgumentValues()));
271+
setPropertyValues(new MutablePropertyValues(original.getPropertyValues()));
261272
setResourceDescription(original.getResourceDescription());
262273
}
263274
}
@@ -294,8 +305,6 @@ public void overrideFrom(BeanDefinition other) {
294305
if (StringUtils.hasLength(other.getFactoryMethodName())) {
295306
setFactoryMethodName(other.getFactoryMethodName());
296307
}
297-
getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
298-
getPropertyValues().addPropertyValues(other.getPropertyValues());
299308
setRole(other.getRole());
300309
setSource(other.getSource());
301310
copyAttributesFrom(other);
@@ -305,6 +314,15 @@ public void overrideFrom(BeanDefinition other) {
305314
if (otherAbd.hasBeanClass()) {
306315
setBeanClass(otherAbd.getBeanClass());
307316
}
317+
if (otherAbd.hasConstructorArgumentValues()) {
318+
getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
319+
}
320+
if (otherAbd.hasPropertyValues()) {
321+
getPropertyValues().addPropertyValues(other.getPropertyValues());
322+
}
323+
if (otherAbd.hasMethodOverrides()) {
324+
getMethodOverrides().addOverrides(otherAbd.getMethodOverrides());
325+
}
308326
setAutowireMode(otherAbd.getAutowireMode());
309327
setDependencyCheck(otherAbd.getDependencyCheck());
310328
setDependsOn(otherAbd.getDependsOn());
@@ -314,7 +332,6 @@ public void overrideFrom(BeanDefinition other) {
314332
setInstanceSupplier(otherAbd.getInstanceSupplier());
315333
setNonPublicAccessAllowed(otherAbd.isNonPublicAccessAllowed());
316334
setLenientConstructorResolution(otherAbd.isLenientConstructorResolution());
317-
getMethodOverrides().addOverrides(otherAbd.getMethodOverrides());
318335
if (otherAbd.getInitMethodName() != null) {
319336
setInitMethodName(otherAbd.getInitMethodName());
320337
setEnforceInitMethod(otherAbd.isEnforceInitMethod());
@@ -327,6 +344,8 @@ public void overrideFrom(BeanDefinition other) {
327344
setResource(otherAbd.getResource());
328345
}
329346
else {
347+
getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
348+
getPropertyValues().addPropertyValues(other.getPropertyValues());
330349
setResourceDescription(other.getResourceDescription());
331350
}
332351
}
@@ -778,46 +797,59 @@ public String getFactoryMethodName() {
778797
/**
779798
* Specify constructor argument values for this bean.
780799
*/
781-
public void setConstructorArgumentValues(@Nullable ConstructorArgumentValues constructorArgumentValues) {
782-
this.constructorArgumentValues =
783-
(constructorArgumentValues != null ? constructorArgumentValues : new ConstructorArgumentValues());
800+
public void setConstructorArgumentValues(ConstructorArgumentValues constructorArgumentValues) {
801+
this.constructorArgumentValues = constructorArgumentValues;
784802
}
785803

786804
/**
787805
* Return constructor argument values for this bean (never {@code null}).
788806
*/
789807
@Override
790808
public ConstructorArgumentValues getConstructorArgumentValues() {
809+
if (this.constructorArgumentValues == null) {
810+
this.constructorArgumentValues = new ConstructorArgumentValues();
811+
}
791812
return this.constructorArgumentValues;
792813
}
793814

794815
/**
795816
* Return if there are constructor argument values defined for this bean.
796817
*/
797818
public boolean hasConstructorArgumentValues() {
798-
return !this.constructorArgumentValues.isEmpty();
819+
return (this.constructorArgumentValues != null && !this.constructorArgumentValues.isEmpty());
799820
}
800821

801822
/**
802823
* Specify property values for this bean, if any.
803824
*/
804-
public void setPropertyValues(@Nullable MutablePropertyValues propertyValues) {
805-
this.propertyValues = (propertyValues != null ? propertyValues : new MutablePropertyValues());
825+
public void setPropertyValues(MutablePropertyValues propertyValues) {
826+
this.propertyValues = propertyValues;
806827
}
807828

808829
/**
809830
* Return property values for this bean (never {@code null}).
810831
*/
811832
@Override
812833
public MutablePropertyValues getPropertyValues() {
834+
if (this.propertyValues == null) {
835+
this.propertyValues = new MutablePropertyValues();
836+
}
813837
return this.propertyValues;
814838
}
815839

840+
/**
841+
* Return if there are property values values defined for this bean.
842+
* @since 5.0.2
843+
*/
844+
public boolean hasPropertyValues() {
845+
return (this.propertyValues != null && !this.propertyValues.isEmpty());
846+
}
847+
816848
/**
817849
* Specify method overrides for the bean, if any.
818850
*/
819-
public void setMethodOverrides(@Nullable MethodOverrides methodOverrides) {
820-
this.methodOverrides = (methodOverrides != null ? methodOverrides : new MethodOverrides());
851+
public void setMethodOverrides(MethodOverrides methodOverrides) {
852+
this.methodOverrides = methodOverrides;
821853
}
822854

823855
/**
@@ -826,9 +858,20 @@ public void setMethodOverrides(@Nullable MethodOverrides methodOverrides) {
826858
* <p>Never returns {@code null}.
827859
*/
828860
public MethodOverrides getMethodOverrides() {
861+
if (this.methodOverrides == null) {
862+
this.methodOverrides = new MethodOverrides();
863+
}
829864
return this.methodOverrides;
830865
}
831866

867+
/**
868+
* Return if there are method overrides defined for this bean.
869+
* @since 5.0.2
870+
*/
871+
public boolean hasMethodOverrides() {
872+
return (this.methodOverrides != null && !this.methodOverrides.isEmpty());
873+
}
874+
832875
/**
833876
* Set the name of the initializer method.
834877
* <p>The default is {@code null} in which case there is no initializer method.
@@ -1002,7 +1045,7 @@ public BeanDefinition getOriginatingBeanDefinition() {
10021045
* @throws BeanDefinitionValidationException in case of validation failure
10031046
*/
10041047
public void validate() throws BeanDefinitionValidationException {
1005-
if (!getMethodOverrides().isEmpty() && getFactoryMethodName() != null) {
1048+
if (hasMethodOverrides() && getFactoryMethodName() != null) {
10061049
throw new BeanDefinitionValidationException(
10071050
"Cannot combine static factory method with method overrides: " +
10081051
"the static factory method must create the instance");
@@ -1020,9 +1063,8 @@ public void validate() throws BeanDefinitionValidationException {
10201063
*/
10211064
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
10221065
// Check that lookup methods exists.
1023-
MethodOverrides methodOverrides = getMethodOverrides();
1024-
if (!methodOverrides.isEmpty()) {
1025-
Set<MethodOverride> overrides = methodOverrides.getOverrides();
1066+
if (hasMethodOverrides()) {
1067+
Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
10261068
synchronized (overrides) {
10271069
for (MethodOverride mo : overrides) {
10281070
prepareMethodOverride(mo);

0 commit comments

Comments
 (0)