Merge branch '5.3.x'
This commit is contained in:
commit
cb44e09694
|
@ -19,8 +19,10 @@ package org.springframework.beans;
|
||||||
import java.beans.IntrospectionException;
|
import java.beans.IntrospectionException;
|
||||||
import java.beans.PropertyDescriptor;
|
import java.beans.PropertyDescriptor;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
@ -52,8 +54,10 @@ abstract class PropertyDescriptorUtils {
|
||||||
* @see SimpleBeanInfoFactory
|
* @see SimpleBeanInfoFactory
|
||||||
* @see java.beans.Introspector#getBeanInfo(Class)
|
* @see java.beans.Introspector#getBeanInfo(Class)
|
||||||
*/
|
*/
|
||||||
public static Collection<PropertyDescriptor> determineBasicProperties(Class<?> beanClass) throws IntrospectionException {
|
public static Collection<? extends PropertyDescriptor> determineBasicProperties(Class<?> beanClass)
|
||||||
Map<String, PropertyDescriptor> pdMap = new TreeMap<>();
|
throws IntrospectionException {
|
||||||
|
|
||||||
|
Map<String, BasicPropertyDescriptor> pdMap = new TreeMap<>();
|
||||||
|
|
||||||
for (Method method : beanClass.getMethods()) {
|
for (Method method : beanClass.getMethods()) {
|
||||||
String methodName = method.getName();
|
String methodName = method.getName();
|
||||||
|
@ -81,39 +85,26 @@ abstract class PropertyDescriptorUtils {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyDescriptor pd = pdMap.get(propertyName);
|
BasicPropertyDescriptor pd = pdMap.get(propertyName);
|
||||||
if (pd != null) {
|
if (pd != null) {
|
||||||
if (setter) {
|
if (setter) {
|
||||||
if (pd.getWriteMethod() == null ||
|
if (pd.getWriteMethod() == null ||
|
||||||
pd.getWriteMethod().getParameterTypes()[0].isAssignableFrom(method.getParameterTypes()[0])) {
|
pd.getWriteMethod().getParameterTypes()[0].isAssignableFrom(method.getParameterTypes()[0])) {
|
||||||
try {
|
|
||||||
pd.setWriteMethod(method);
|
pd.setWriteMethod(method);
|
||||||
}
|
}
|
||||||
catch (IntrospectionException ex) {
|
else {
|
||||||
// typically a type mismatch -> ignore
|
pd.addWriteMethod(method);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (pd.getReadMethod() == null ||
|
if (pd.getReadMethod() == null ||
|
||||||
(pd.getReadMethod().getReturnType() == method.getReturnType() && method.getName().startsWith("is"))) {
|
(pd.getReadMethod().getReturnType() == method.getReturnType() && method.getName().startsWith("is"))) {
|
||||||
try {
|
|
||||||
pd.setReadMethod(method);
|
pd.setReadMethod(method);
|
||||||
}
|
}
|
||||||
catch (IntrospectionException ex) {
|
|
||||||
// typically a type mismatch -> ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pd = new BasicPropertyDescriptor(propertyName, beanClass);
|
pd = new BasicPropertyDescriptor(propertyName, (!setter ? method : null), (setter ? method : null));
|
||||||
if (setter) {
|
|
||||||
pd.setWriteMethod(method);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pd.setReadMethod(method);
|
|
||||||
}
|
|
||||||
pdMap.put(propertyName, pd);
|
pdMap.put(propertyName, pd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,8 +268,12 @@ abstract class PropertyDescriptorUtils {
|
||||||
@Nullable
|
@Nullable
|
||||||
private Method writeMethod;
|
private Method writeMethod;
|
||||||
|
|
||||||
public BasicPropertyDescriptor(String propertyName, Class<?> beanClass) throws IntrospectionException {
|
private final List<Method> alternativeWriteMethods = new ArrayList<>();
|
||||||
super(propertyName, beanClass, null, null);
|
|
||||||
|
public BasicPropertyDescriptor(String propertyName, @Nullable Method readMethod, @Nullable Method writeMethod)
|
||||||
|
throws IntrospectionException {
|
||||||
|
|
||||||
|
super(propertyName, readMethod, writeMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -297,11 +292,33 @@ abstract class PropertyDescriptorUtils {
|
||||||
this.writeMethod = writeMethod;
|
this.writeMethod = writeMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addWriteMethod(Method writeMethod) {
|
||||||
|
if (this.writeMethod != null) {
|
||||||
|
this.alternativeWriteMethods.add(this.writeMethod);
|
||||||
|
this.writeMethod = null;
|
||||||
|
}
|
||||||
|
this.alternativeWriteMethods.add(writeMethod);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public Method getWriteMethod() {
|
public Method getWriteMethod() {
|
||||||
|
if (this.writeMethod == null && !this.alternativeWriteMethods.isEmpty()) {
|
||||||
|
if (this.readMethod == null) {
|
||||||
|
return this.alternativeWriteMethods.get(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (Method method : this.alternativeWriteMethods) {
|
||||||
|
if (this.readMethod.getReturnType().isAssignableFrom(method.getParameterTypes()[0])) {
|
||||||
|
this.writeMethod = method;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return this.writeMethod;
|
return this.writeMethod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,9 @@ class SimpleBeanInfoFactory implements BeanInfoFactory, Ordered {
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
@NonNull
|
||||||
public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
|
public BeanInfo getBeanInfo(Class<?> beanClass) throws IntrospectionException {
|
||||||
Collection<PropertyDescriptor> pds = PropertyDescriptorUtils.determineBasicProperties(beanClass);
|
Collection<? extends PropertyDescriptor> pds =
|
||||||
|
PropertyDescriptorUtils.determineBasicProperties(beanClass);
|
||||||
|
|
||||||
return new SimpleBeanInfo() {
|
return new SimpleBeanInfo() {
|
||||||
@Override
|
@Override
|
||||||
public PropertyDescriptor[] getPropertyDescriptors() {
|
public PropertyDescriptor[] getPropertyDescriptors() {
|
||||||
|
|
|
@ -153,6 +153,16 @@ class BeanWrapperTests extends AbstractPropertyAccessorTests {
|
||||||
assertThat(accessor.getPropertyValue("object")).isEqualTo(8);
|
assertThat(accessor.getPropertyValue("object")).isEqualTo(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void setterOverload() {
|
||||||
|
SetterOverload target = new SetterOverload();
|
||||||
|
BeanWrapper accessor = createAccessor(target);
|
||||||
|
accessor.setPropertyValue("object", "a String");
|
||||||
|
assertThat(target.value).isEqualTo("a String");
|
||||||
|
assertThat(target.getObject()).isEqualTo("a String");
|
||||||
|
assertThat(accessor.getPropertyValue("object")).isEqualTo("a String");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void propertyDescriptors() throws Exception {
|
void propertyDescriptors() throws Exception {
|
||||||
TestBean target = new TestBean();
|
TestBean target = new TestBean();
|
||||||
|
@ -348,6 +358,24 @@ class BeanWrapperTests extends AbstractPropertyAccessorTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class SetterOverload {
|
||||||
|
|
||||||
|
public String value;
|
||||||
|
|
||||||
|
public void setObject(Integer length) {
|
||||||
|
this.value = length.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setObject(String object) {
|
||||||
|
this.value = object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getObject() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class GetterWithOptional {
|
public static class GetterWithOptional {
|
||||||
|
|
||||||
public TestBean value;
|
public TestBean value;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2021 the original author or authors.
|
* Copyright 2002-2022 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -95,6 +95,8 @@ public class Jsr310DateTimeFormatAnnotationFormatterFactory extends EmbeddedValu
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Parser<?> getParser(DateTimeFormat annotation, Class<?> fieldType) {
|
public Parser<?> getParser(DateTimeFormat annotation, Class<?> fieldType) {
|
||||||
|
DateTimeFormatter formatter = getFormatter(annotation, fieldType);
|
||||||
|
|
||||||
List<String> resolvedFallbackPatterns = new ArrayList<>();
|
List<String> resolvedFallbackPatterns = new ArrayList<>();
|
||||||
for (String fallbackPattern : annotation.fallbackPatterns()) {
|
for (String fallbackPattern : annotation.fallbackPatterns()) {
|
||||||
String resolvedFallbackPattern = resolveEmbeddedValue(fallbackPattern);
|
String resolvedFallbackPattern = resolveEmbeddedValue(fallbackPattern);
|
||||||
|
@ -103,7 +105,6 @@ public class Jsr310DateTimeFormatAnnotationFormatterFactory extends EmbeddedValu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTimeFormatter formatter = getFormatter(annotation, fieldType);
|
|
||||||
return new TemporalAccessorParser((Class<? extends TemporalAccessor>) fieldType,
|
return new TemporalAccessorParser((Class<? extends TemporalAccessor>) fieldType,
|
||||||
formatter, resolvedFallbackPatterns.toArray(new String[0]), annotation);
|
formatter, resolvedFallbackPatterns.toArray(new String[0]), annotation);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue