Expose autoGrowCollectionLimit in ConfigurablePropertyAccessor interface

See gh-36862
This commit is contained in:
Juergen Hoeller
2026-06-02 17:20:52 +02:00
parent 481a5743b3
commit e6ce2a3c36
5 changed files with 36 additions and 26 deletions
@@ -76,8 +76,6 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
*/
private static final Log logger = LogFactory.getLog(AbstractNestablePropertyAccessor.class);
private int autoGrowCollectionLimit = Integer.MAX_VALUE;
@Nullable Object wrappedObject;
private String nestedPath = "";
@@ -156,21 +154,6 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
}
/**
* Specify a limit for array and collection auto-growing.
* <p>Default is unlimited on a plain accessor.
*/
public void setAutoGrowCollectionLimit(int autoGrowCollectionLimit) {
this.autoGrowCollectionLimit = autoGrowCollectionLimit;
}
/**
* Return the limit for array and collection auto-growing.
*/
public int getAutoGrowCollectionLimit() {
return this.autoGrowCollectionLimit;
}
/**
* Switch the target object, replacing the cached introspection results only
* if the class of the new object is different to that of the replaced object.
@@ -298,7 +281,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
componentType, ph.nested(tokens.keys.length));
int length = Array.getLength(propValue);
if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {
if (arrayIndex >= length && arrayIndex < getAutoGrowCollectionLimit()) {
Object newArray = Array.newInstance(componentType, arrayIndex + 1);
System.arraycopy(propValue, 0, newArray, 0, length);
int lastKeyIndex = tokens.canonicalName.lastIndexOf('[');
@@ -324,7 +307,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
requiredType.getResolvableType().resolve(), requiredType);
int size = list.size();
if (index >= size && index < this.autoGrowCollectionLimit) {
if (index >= size && index < getAutoGrowCollectionLimit()) {
for (int i = size; i < index; i++) {
try {
list.add(null);
@@ -761,7 +744,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
return array;
}
int length = Array.getLength(array);
if (index >= length && index < this.autoGrowCollectionLimit) {
if (index >= length && index < getAutoGrowCollectionLimit()) {
Class<?> componentType = array.getClass().componentType();
Object newArray = Array.newInstance(componentType, index + 1);
System.arraycopy(array, 0, newArray, 0, length);
@@ -785,7 +768,7 @@ public abstract class AbstractNestablePropertyAccessor extends AbstractPropertyA
return;
}
int size = collection.size();
if (index >= size && index < this.autoGrowCollectionLimit) {
if (index >= size && index < getAutoGrowCollectionLimit()) {
Class<?> elementType = ph.getResolvableType().getNested(nestingLevel).asCollection().resolveGeneric();
if (elementType != null) {
for (int i = collection.size(); i < index + 1; i++) {
@@ -40,6 +40,8 @@ public abstract class AbstractPropertyAccessor extends TypeConverterSupport impl
private boolean autoGrowNestedPaths = false;
private int autoGrowCollectionLimit = Integer.MAX_VALUE;
boolean suppressNotWritablePropertyException = false;
@@ -63,6 +65,16 @@ public abstract class AbstractPropertyAccessor extends TypeConverterSupport impl
return this.autoGrowNestedPaths;
}
@Override
public void setAutoGrowCollectionLimit(int autoGrowCollectionLimit) {
this.autoGrowCollectionLimit = autoGrowCollectionLimit;
}
@Override
public int getAutoGrowCollectionLimit() {
return this.autoGrowCollectionLimit;
}
@Override
public void setPropertyValue(PropertyValue pv) throws BeansException {
@@ -63,13 +63,28 @@ public interface ConfigurablePropertyAccessor extends PropertyAccessor, Property
* <p>If {@code true}, a {@code null} path location will be populated
* with a default object value and traversed instead of resulting in a
* {@link NullValueInNestedPathException}.
* <p>Default is {@code false} on a plain PropertyAccessor instance.
* <p>Default is {@code false} on a plain accessor.
* @since 4.1
*/
void setAutoGrowNestedPaths(boolean autoGrowNestedPaths);
/**
* Return whether "auto-growing" of nested paths has been activated.
* @since 4.1
*/
boolean isAutoGrowNestedPaths();
/**
* Specify a limit for array and collection auto-growing.
* <p>Default is unlimited on a plain accessor.
* @since 7.1
*/
void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);
/**
* Return the limit for array and collection auto-growing.
* @since 7.1
*/
int getAutoGrowCollectionLimit();
}
@@ -273,8 +273,9 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
* Specify the limit for array and collection auto-growing.
* <p>Default is 256, preventing OutOfMemoryErrors in case of large indexes.
* Raise this limit if your auto-growing needs are unusually high.
* <p>Used for setter/field injection via {@link #bind(PropertyValues)}, and not
* applicable to constructor binding via {@link #construct}.
* <p>Used for setter injection - and as of 7.1 also for field injection -
* via {@link #bind(PropertyValues)}; not applicable to constructor binding
* via {@link #construct}.
* @see #initBeanPropertyAccess()
* @see org.springframework.beans.BeanWrapper#setAutoGrowCollectionLimit
*/
@@ -19,7 +19,6 @@ package org.springframework.validation;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.ConfigurablePropertyAccessor;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.PropertyAccessorFactory;
/**
@@ -100,7 +99,7 @@ public class DirectFieldBindingResult extends AbstractPropertyBindingResult {
this.directFieldAccessor = createDirectFieldAccessor();
this.directFieldAccessor.setExtractOldValueForEditor(true);
this.directFieldAccessor.setAutoGrowNestedPaths(this.autoGrowNestedPaths);
((DirectFieldAccessor) this.directFieldAccessor).setAutoGrowCollectionLimit(this.autoGrowCollectionLimit);
this.directFieldAccessor.setAutoGrowCollectionLimit(this.autoGrowCollectionLimit);
}
return this.directFieldAccessor;
}