Do not treat void and Void as simple types in BeanUtils

Prior to this commit, the isSimpleProperty() and isSimpleValueType()
methods in BeanUtils treated void and Void as simple types; however,
doing so does not make sense in this context, since void implies the
lack of a property or value.

This commit addresses this by explicitly excluding void and Void in the
logic in isSimpleValueType().

This commit also simplifies the implementation of
ViewResolutionResultHandler.supports(HandlerResult) to take advantage
of this change.

Closes gh-23573
This commit is contained in:
Sam Brannen 2019-09-04 15:48:40 +02:00
parent 3a132f8c3c
commit d036b5a283
3 changed files with 101 additions and 25 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -554,35 +554,42 @@ public abstract class BeanUtils {
}
/**
* Check if the given type represents a "simple" property:
* a primitive, a String or other CharSequence, a Number, a Date,
* a URI, a URL, a Locale, a Class, or a corresponding array.
* Check if the given type represents a "simple" property: a simple value
* type or an array of simple value types.
* <p>See {@link #isSimpleValueType(Class)} for the definition of <em>simple
* value type</em>.
* <p>Used to determine properties to check for a "simple" dependency-check.
* @param clazz the type to check
* @param type the type to check
* @return whether the given type represents a "simple" property
* @see org.springframework.beans.factory.support.RootBeanDefinition#DEPENDENCY_CHECK_SIMPLE
* @see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#checkDependencies
* @see #isSimpleValueType(Class)
*/
public static boolean isSimpleProperty(Class<?> clazz) {
Assert.notNull(clazz, "Class must not be null");
return isSimpleValueType(clazz) || (clazz.isArray() && isSimpleValueType(clazz.getComponentType()));
public static boolean isSimpleProperty(Class<?> type) {
Assert.notNull(type, "'type' must not be null");
return isSimpleValueType(type) || (type.isArray() && isSimpleValueType(type.getComponentType()));
}
/**
* Check if the given type represents a "simple" value type:
* a primitive, an enum, a String or other CharSequence, a Number, a Date,
* a URI, a URL, a Locale or a Class.
* @param clazz the type to check
* Check if the given type represents a "simple" value type: a primitive or
* primitive wrapper, an enum, a String or other CharSequence, a Number, a
* Date, a URI, a URL, a Locale, or a Class.
* <p>{@code Void} and {@code void} are not considered simple value types.
* @param type the type to check
* @return whether the given type represents a "simple" value type
* @see #isSimpleProperty(Class)
*/
public static boolean isSimpleValueType(Class<?> clazz) {
return (ClassUtils.isPrimitiveOrWrapper(clazz) ||
Enum.class.isAssignableFrom(clazz) ||
CharSequence.class.isAssignableFrom(clazz) ||
Number.class.isAssignableFrom(clazz) ||
Date.class.isAssignableFrom(clazz) ||
URI.class == clazz || URL.class == clazz ||
Locale.class == clazz || Class.class == clazz);
public static boolean isSimpleValueType(Class<?> type) {
return (type != void.class && type != Void.class &&
(ClassUtils.isPrimitiveOrWrapper(type) ||
Enum.class.isAssignableFrom(type) ||
CharSequence.class.isAssignableFrom(type) ||
Number.class.isAssignableFrom(type) ||
Date.class.isAssignableFrom(type) ||
URI.class == type ||
URL.class == type ||
Locale.class == type ||
Class.class == type));
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -19,8 +19,14 @@ package org.springframework.beans;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.time.DayOfWeek;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.stream.Stream;
import org.junit.Test;
@ -32,7 +38,12 @@ import org.springframework.tests.sample.beans.DerivedTestBean;
import org.springframework.tests.sample.beans.ITestBean;
import org.springframework.tests.sample.beans.TestBean;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Unit tests for {@link BeanUtils}.
@ -40,6 +51,7 @@ import static org.junit.Assert.*;
* @author Juergen Hoeller
* @author Rob Harrop
* @author Chris Beams
* @author Sam Brannen
* @since 19.05.2003
*/
public class BeanUtilsTests {
@ -275,6 +287,60 @@ public class BeanUtilsTests {
}
}
@Test
public void isSimpleValueType() {
Stream.of(
boolean.class, char.class, byte.class, short.class, int.class,
long.class, float.class, double.class,
Boolean.class, Character.class, Byte.class, Short.class, Integer.class,
Long.class, Float.class, Double.class,
DayOfWeek.class, String.class, Date.class, URI.class, URL.class, Locale.class, Class.class
).forEach(this::assertIsSimpleValueType);
Stream.of(int[].class, Object.class, List.class, void.class, Void.class)
.forEach(this::assertIsNotSimpleValueType);
}
@Test
public void isSimpleProperty() {
Stream.of(
boolean.class, char.class, byte.class, short.class, int.class,
long.class, float.class, double.class,
Boolean.class, Character.class, Byte.class, Short.class, Integer.class,
Long.class, Float.class, Double.class,
DayOfWeek.class, String.class, Date.class, URI.class, URL.class, Locale.class, Class.class,
boolean[].class, Boolean[].class, Date[].class
).forEach(this::assertIsSimpleProperty);
Stream.of(Object.class, List.class, void.class, Void.class)
.forEach(this::assertIsNotSimpleProperty);
}
private void assertIsSimpleValueType(Class<?> type) {
assertTrue("Type [" + type.getName() + "] should be a simple value type", BeanUtils.isSimpleValueType(type));
}
private void assertIsNotSimpleValueType(Class<?> type) {
assertFalse("Type [" + type.getName() + "] should not be a simple value type", BeanUtils.isSimpleValueType(type));
}
private void assertIsSimpleProperty(Class<?> type) {
assertTrue("Type [" + type.getName() + "] should be a simple property", BeanUtils.isSimpleProperty(type));
}
private void assertIsNotSimpleProperty(Class<?> type) {
assertFalse("Type [" + type.getName() + "] should not be a simple property", BeanUtils.isSimpleProperty(type));
}
private void assertSignatureEquals(Method desiredMethod, String signature) {
assertEquals(desiredMethod, BeanUtils.resolveSignature(signature, MethodSignatureBean.class));
}
@ -445,6 +511,7 @@ public class BeanUtilsTests {
}
}
@SuppressWarnings("unused")
private static class BeanWithSingleNonDefaultConstructor {
private final String name;

View File

@ -160,9 +160,11 @@ public class ViewResolutionResultHandler extends HandlerResultHandlerSupport
type = result.getReturnType().getGeneric().toClass();
}
return (CharSequence.class.isAssignableFrom(type) || Rendering.class.isAssignableFrom(type) ||
Model.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type) ||
Void.class.equals(type) || void.class.equals(type) || View.class.isAssignableFrom(type) ||
return (CharSequence.class.isAssignableFrom(type) ||
Rendering.class.isAssignableFrom(type) ||
Model.class.isAssignableFrom(type) ||
Map.class.isAssignableFrom(type) ||
View.class.isAssignableFrom(type) ||
!BeanUtils.isSimpleProperty(type));
}