use TypeDescriptor.forObject instead of constructor; enforce use of TypeDescriptor.valueOf through making the constructor private
This commit is contained in:
parent
7fb19d658b
commit
dc99df2972
|
|
@ -194,7 +194,7 @@ class TypeConverterDelegate {
|
|||
// No custom editor but custom ConversionService specified?
|
||||
ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
|
||||
if (editor == null && conversionService != null && convertedValue != null) {
|
||||
TypeDescriptor sourceTypeDesc = new TypeDescriptor(convertedValue);
|
||||
TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(convertedValue);
|
||||
if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
|
||||
return (T) conversionService.convert(convertedValue, sourceTypeDesc, typeDescriptor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,39 +43,38 @@ public class TypeDescriptor {
|
|||
private static final Map<Class<?>, TypeDescriptor> typeDescriptorCache = new HashMap<Class<?>, TypeDescriptor>();
|
||||
|
||||
static {
|
||||
typeDescriptorCache.put(boolean.class, new TypeDescriptor(boolean.class));
|
||||
typeDescriptorCache.put(Boolean.class, new TypeDescriptor(Boolean.class));
|
||||
|
||||
typeDescriptorCache.put(byte.class, new TypeDescriptor(byte.class));
|
||||
typeDescriptorCache.put(Byte.class, new TypeDescriptor(Byte.class));
|
||||
|
||||
typeDescriptorCache.put(char.class, new TypeDescriptor(char.class));
|
||||
typeDescriptorCache.put(Character.class, new TypeDescriptor(Character.class));
|
||||
|
||||
typeDescriptorCache.put(boolean.class, new TypeDescriptor(boolean.class));
|
||||
typeDescriptorCache.put(Boolean.class, new TypeDescriptor(Boolean.class));
|
||||
|
||||
typeDescriptorCache.put(short.class, new TypeDescriptor(short.class));
|
||||
typeDescriptorCache.put(Short.class, new TypeDescriptor(Short.class));
|
||||
|
||||
typeDescriptorCache.put(double.class, new TypeDescriptor(double.class));
|
||||
typeDescriptorCache.put(Double.class, new TypeDescriptor(Double.class));
|
||||
|
||||
typeDescriptorCache.put(float.class, new TypeDescriptor(float.class));
|
||||
typeDescriptorCache.put(Float.class, new TypeDescriptor(Float.class));
|
||||
|
||||
typeDescriptorCache.put(int.class, new TypeDescriptor(int.class));
|
||||
typeDescriptorCache.put(Integer.class, new TypeDescriptor(Integer.class));
|
||||
|
||||
typeDescriptorCache.put(long.class, new TypeDescriptor(long.class));
|
||||
typeDescriptorCache.put(Long.class, new TypeDescriptor(Long.class));
|
||||
|
||||
typeDescriptorCache.put(float.class, new TypeDescriptor(float.class));
|
||||
typeDescriptorCache.put(Float.class, new TypeDescriptor(Float.class));
|
||||
|
||||
typeDescriptorCache.put(double.class, new TypeDescriptor(double.class));
|
||||
typeDescriptorCache.put(Double.class, new TypeDescriptor(Double.class));
|
||||
|
||||
typeDescriptorCache.put(short.class, new TypeDescriptor(short.class));
|
||||
typeDescriptorCache.put(Short.class, new TypeDescriptor(Short.class));
|
||||
|
||||
typeDescriptorCache.put(String.class, new TypeDescriptor(String.class));
|
||||
}
|
||||
|
||||
|
||||
private Object value;
|
||||
|
||||
private Class<?> type;
|
||||
|
||||
private TypeDescriptor elementType;
|
||||
|
||||
private MethodParameter methodParameter;
|
||||
|
||||
private Field field;
|
||||
|
|
@ -83,17 +82,6 @@ public class TypeDescriptor {
|
|||
private Annotation[] cachedFieldAnnotations;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new descriptor for the given type.
|
||||
* <p>Use this constructor when a conversion point comes from a plain source type,
|
||||
* where no additional context is available.
|
||||
* @param type the actual type to wrap
|
||||
*/
|
||||
public TypeDescriptor(Class<?> type) {
|
||||
Assert.notNull(type, "Type must not be null");
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new type descriptor from a method or constructor parameter.
|
||||
* <p>Use this constructor when a target conversion point originates from a method parameter,
|
||||
|
|
@ -115,18 +103,6 @@ public class TypeDescriptor {
|
|||
this.field = field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new descriptor for the type of the given value.
|
||||
* <p>Use this constructor when a conversion point comes from a source such as a Map or
|
||||
* Collection, where no additional context is available but elements can be introspected.
|
||||
* @param type the actual type to wrap
|
||||
*/
|
||||
public TypeDescriptor(Object value) {
|
||||
Assert.notNull(value, "Value must not be null");
|
||||
this.value = value;
|
||||
this.type = value.getClass();
|
||||
}
|
||||
|
||||
// protected constructors for subclasses
|
||||
|
||||
/**
|
||||
|
|
@ -148,6 +124,30 @@ public class TypeDescriptor {
|
|||
private TypeDescriptor() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new descriptor for the type of the given value.
|
||||
* <p>Use this constructor when a conversion point comes from a source such as a Map or
|
||||
* Collection, where no additional context is available but elements can be introspected.
|
||||
* @param type the actual type to wrap
|
||||
*/
|
||||
private TypeDescriptor(Object value) {
|
||||
Assert.notNull(value, "Value must not be null");
|
||||
this.value = value;
|
||||
this.type = value.getClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new descriptor for the given type.
|
||||
* <p>Use this constructor when a conversion point comes from a plain source type,
|
||||
* where no additional context is available.
|
||||
* @param type the actual type to wrap
|
||||
*/
|
||||
private TypeDescriptor(Class<?> type) {
|
||||
Assert.notNull(type, "Type must not be null");
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the wrapped MethodParameter, if any.
|
||||
* <p>Note: Either MethodParameter or Field is available.
|
||||
|
|
@ -237,19 +237,14 @@ public class TypeDescriptor {
|
|||
* Return the element type as a type descriptor.
|
||||
*/
|
||||
public TypeDescriptor getElementTypeDescriptor() {
|
||||
if (this.elementType != null) {
|
||||
return this.elementType;
|
||||
if (isArray()) {
|
||||
return TypeDescriptor.valueOf(getArrayComponentType());
|
||||
}
|
||||
else if (isCollection()) {
|
||||
return TypeDescriptor.valueOf(getCollectionElementType());
|
||||
}
|
||||
else {
|
||||
if (isArray()) {
|
||||
return TypeDescriptor.valueOf(getArrayComponentType());
|
||||
}
|
||||
else if (isCollection()) {
|
||||
return TypeDescriptor.valueOf(getCollectionElementType());
|
||||
}
|
||||
else {
|
||||
return TypeDescriptor.NULL;
|
||||
}
|
||||
return TypeDescriptor.NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -426,30 +421,7 @@ public class TypeDescriptor {
|
|||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
// static factory methods
|
||||
|
||||
/**
|
||||
* Creates a new type descriptor for the given class.
|
||||
* @param type the class
|
||||
* @return the type descriptor
|
||||
*/
|
||||
public static TypeDescriptor valueOf(Class<?> type) {
|
||||
if (type == null) {
|
||||
return TypeDescriptor.NULL;
|
||||
}
|
||||
TypeDescriptor desc = typeDescriptorCache.get(type);
|
||||
return desc != null ? desc : new TypeDescriptor(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new type descriptor for the class of the given object.
|
||||
* @param object the object
|
||||
* @return the type descriptor
|
||||
*/
|
||||
public static TypeDescriptor forObject(Object object) {
|
||||
return (object == null ? NULL : valueOf(object.getClass()));
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
|
|
@ -486,5 +458,38 @@ public class TypeDescriptor {
|
|||
Class<?> type = getType();
|
||||
return (type != null && ClassUtils.isAssignable(clazz, type));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// static factory methods
|
||||
|
||||
/**
|
||||
* Create a new type descriptor for the given class.
|
||||
* @param type the class
|
||||
* @return the type descriptor
|
||||
*/
|
||||
public static TypeDescriptor valueOf(Class<?> type) {
|
||||
if (type == null) {
|
||||
return TypeDescriptor.NULL;
|
||||
}
|
||||
TypeDescriptor desc = typeDescriptorCache.get(type);
|
||||
return (desc != null ? desc : new TypeDescriptor(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new type descriptor for the class of the given object.
|
||||
* @param object the object
|
||||
* @return the type descriptor
|
||||
*/
|
||||
public static TypeDescriptor forObject(Object object) {
|
||||
if (object == null) {
|
||||
return NULL;
|
||||
}
|
||||
else if (object instanceof Collection || object instanceof Map) {
|
||||
return new TypeDescriptor(object);
|
||||
}
|
||||
else {
|
||||
return valueOf(object.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,10 +58,8 @@ public abstract class ReflectionUtils {
|
|||
* the supplied <code>name</code> and/or {@link Class type}. Searches all
|
||||
* superclasses up to {@link Object}.
|
||||
* @param clazz the class to introspect
|
||||
* @param name the name of the field (may be <code>null</code> if type is
|
||||
* specified)
|
||||
* @param type the type of the field (may be <code>null</code> if name is
|
||||
* specified)
|
||||
* @param name the name of the field (may be <code>null</code> if type is specified)
|
||||
* @param type the type of the field (may be <code>null</code> if name is specified)
|
||||
* @return the corresponding Field object, or <code>null</code> if not found
|
||||
*/
|
||||
public static Field findField(Class<?> clazz, String name, Class<?> type) {
|
||||
|
|
@ -81,13 +79,11 @@ public abstract class ReflectionUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set the field represented by the supplied {@link Field field object} on
|
||||
* the specified {@link Object target object} to the specified
|
||||
* <code>value</code>. In accordance with {@link Field#set(Object, Object)}
|
||||
* semantics, the new value is automatically unwrapped if the underlying
|
||||
* field has a primitive type.
|
||||
* <p>Thrown exceptions are handled via a call to
|
||||
* {@link #handleReflectionException(Exception)}.
|
||||
* Set the field represented by the supplied {@link Field field object} on the
|
||||
* specified {@link Object target object} to the specified <code>value</code>.
|
||||
* In accordance with {@link Field#set(Object, Object)} semantics, the new value
|
||||
* is automatically unwrapped if the underlying field has a primitive type.
|
||||
* <p>Thrown exceptions are handled via a call to {@link #handleReflectionException(Exception)}.
|
||||
* @param field the field to set
|
||||
* @param target the target object on which to set the field
|
||||
* @param value the value to set; may be <code>null</code>
|
||||
|
|
@ -104,12 +100,11 @@ public abstract class ReflectionUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the field represented by the supplied {@link Field field object} on
|
||||
* the specified {@link Object target object}. In accordance with
|
||||
* {@link Field#get(Object)} semantics, the returned value is automatically
|
||||
* wrapped if the underlying field has a primitive type.
|
||||
* <p>Thrown exceptions are handled via a call to
|
||||
* {@link #handleReflectionException(Exception)}.
|
||||
* Get the field represented by the supplied {@link Field field object} on the
|
||||
* specified {@link Object target object}. In accordance with {@link Field#get(Object)}
|
||||
* semantics, the returned value is automatically wrapped if the underlying field
|
||||
* has a primitive type.
|
||||
* <p>Thrown exceptions are handled via a call to {@link #handleReflectionException(Exception)}.
|
||||
* @param field the field to get
|
||||
* @param target the target object from which to get the field
|
||||
* @return the field's current value
|
||||
|
|
@ -126,9 +121,8 @@ public abstract class ReflectionUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Attempt to find a {@link Method} on the supplied class with the supplied
|
||||
* name and no parameters. Searches all superclasses up to
|
||||
* <code>Object</code>.
|
||||
* Attempt to find a {@link Method} on the supplied class with the supplied name
|
||||
* and no parameters. Searches all superclasses up to <code>Object</code>.
|
||||
* <p>Returns <code>null</code> if no {@link Method} can be found.
|
||||
* @param clazz the class to introspect
|
||||
* @param name the name of the method
|
||||
|
|
@ -139,14 +133,13 @@ public abstract class ReflectionUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Attempt to find a {@link Method} on the supplied class with the supplied
|
||||
* name and parameter types. Searches all superclasses up to
|
||||
* <code>Object</code>.
|
||||
* Attempt to find a {@link Method} on the supplied class with the supplied name
|
||||
* and parameter types. Searches all superclasses up to <code>Object</code>.
|
||||
* <p>Returns <code>null</code> if no {@link Method} can be found.
|
||||
* @param clazz the class to introspect
|
||||
* @param name the name of the method
|
||||
* @param paramTypes the parameter types of the method (may be
|
||||
* <code>null</code> to indicate any signature)
|
||||
* @param paramTypes the parameter types of the method
|
||||
* (may be <code>null</code> to indicate any signature)
|
||||
* @return the Method object, or <code>null</code> if none found
|
||||
*/
|
||||
public static Method findMethod(Class<?> clazz, String name, Class<?>... paramTypes) {
|
||||
|
|
@ -167,11 +160,9 @@ public abstract class ReflectionUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Invoke the specified {@link Method} against the supplied target object
|
||||
* with no arguments. The target object can be <code>null</code> when
|
||||
* invoking a static {@link Method}.
|
||||
* <p>Thrown exceptions are handled via a call to
|
||||
* {@link #handleReflectionException}.
|
||||
* Invoke the specified {@link Method} against the supplied target object with no arguments.
|
||||
* The target object can be <code>null</code> when invoking a static {@link Method}.
|
||||
* <p>Thrown exceptions are handled via a call to {@link #handleReflectionException}.
|
||||
* @param method the method to invoke
|
||||
* @param target the target object to invoke the method on
|
||||
* @return the invocation result, if any
|
||||
|
|
@ -182,11 +173,10 @@ public abstract class ReflectionUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Invoke the specified {@link Method} against the supplied target object
|
||||
* with the supplied arguments. The target object can be <code>null</code>
|
||||
* when invoking a static {@link Method}.
|
||||
* <p>Thrown exceptions are handled via a call to
|
||||
* {@link #handleReflectionException}.
|
||||
* Invoke the specified {@link Method} against the supplied target object with the
|
||||
* supplied arguments. The target object can be <code>null</code> when invoking a
|
||||
* static {@link Method}.
|
||||
* <p>Thrown exceptions are handled via a call to {@link #handleReflectionException}.
|
||||
* @param method the method to invoke
|
||||
* @param target the target object to invoke the method on
|
||||
* @param args the invocation arguments (may be <code>null</code>)
|
||||
|
|
@ -548,7 +538,6 @@ public abstract class ReflectionUtils {
|
|||
+ "] must be same or subclass as source class [" + src.getClass().getName() + "]");
|
||||
}
|
||||
doWithFields(src.getClass(), new FieldCallback() {
|
||||
|
||||
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
|
||||
makeAccessible(field);
|
||||
Object srcValue = field.get(src);
|
||||
|
|
|
|||
|
|
@ -16,12 +16,11 @@
|
|||
|
||||
package org.springframework.core.convert;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
|
|
@ -53,7 +52,7 @@ public class TypeDescriptorTests {
|
|||
|
||||
@Test
|
||||
public void buildingArrayTypeDescriptors() throws Exception {
|
||||
TypeDescriptor typeDescriptor = new TypeDescriptor(new int[0].getClass());
|
||||
TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(int[].class);
|
||||
assertTrue(typeDescriptor.isArray());
|
||||
assertEquals(Integer.TYPE,typeDescriptor.getElementType());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue