Avoid pre-conversion attempt in case of overloaded write methods

Closes gh-32159
See gh-31872
This commit is contained in:
Juergen Hoeller
2024-01-30 21:57:14 +01:00
parent 067638ae6e
commit af5acb6d34
4 changed files with 105 additions and 21 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -607,6 +607,22 @@ public abstract class BeanUtils {
return Object.class;
}
/**
* Determine whether the specified property has a unique write method,
* i.e. is writable but does not declare overloaded setter methods.
* @param pd the PropertyDescriptor for the property
* @return {@code true} if writable and unique, {@code false} otherwise
* @since 6.1.4
*/
public static boolean hasUniqueWriteMethod(PropertyDescriptor pd) {
if (pd instanceof GenericTypeAwarePropertyDescriptor gpd) {
return gpd.hasUniqueWriteMethod();
}
else {
return (pd.getWriteMethod() != null);
}
}
/**
* Obtain a new MethodParameter object for the write method of the
* specified property.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -171,6 +171,10 @@ final class GenericTypeAwarePropertyDescriptor extends PropertyDescriptor {
return null;
}
public boolean hasUniqueWriteMethod() {
return (this.writeMethod != null && this.ambiguousWriteMethods == null);
}
public MethodParameter getWriteMethodParameter() {
Assert.state(this.writeMethodParameter != null, "No write method available");
return this.writeMethodParameter;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,6 +39,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.BeansException;
import org.springframework.beans.InvalidPropertyException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyAccessorUtils;
import org.springframework.beans.PropertyValue;
@@ -1683,8 +1684,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
}
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
boolean convertible = isConvertibleProperty(propertyName, bw);
if (convertible) {
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
@@ -1721,6 +1721,19 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
}
}
/**
* Determine whether the factory should cache a converted value for the given property.
*/
private boolean isConvertibleProperty(String propertyName, BeanWrapper bw) {
try {
return !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName) &&
BeanUtils.hasUniqueWriteMethod(bw.getPropertyDescriptor(propertyName));
}
catch (InvalidPropertyException ex) {
return false;
}
}
/**
* Convert the given value for the specified target property.
*/