Introduce ResolvableType.toClass() shortcut

Issue: SPR-17086
This commit is contained in:
Juergen Hoeller 2018-07-25 14:15:19 +02:00
parent 31bfc1dc2b
commit fd8e4abe5d
26 changed files with 40 additions and 28 deletions

View File

@ -159,12 +159,12 @@ public final class BridgeMethodResolver {
Class<?> candidateParameter = candidateParameters[i]; Class<?> candidateParameter = candidateParameters[i];
if (candidateParameter.isArray()) { if (candidateParameter.isArray()) {
// An array type: compare the component type. // An array type: compare the component type.
if (!candidateParameter.getComponentType().equals(genericParameter.getComponentType().resolve(Object.class))) { if (!candidateParameter.getComponentType().equals(genericParameter.getComponentType().toClass())) {
return false; return false;
} }
} }
// A non-array type: compare the type itself. // A non-array type: compare the type itself.
if (!candidateParameter.equals(genericParameter.resolve(Object.class))) { if (!candidateParameter.equals(genericParameter.toClass())) {
return false; return false;
} }
} }

View File

@ -212,7 +212,7 @@ public final class Conventions {
ReactiveAdapter adapter = reactiveAdapterRegistry.getAdapter(valueClass); ReactiveAdapter adapter = reactiveAdapterRegistry.getAdapter(valueClass);
if (adapter != null && !adapter.getDescriptor().isNoValue()) { if (adapter != null && !adapter.getDescriptor().isNoValue()) {
reactiveSuffix = ClassUtils.getShortName(valueClass); reactiveSuffix = ClassUtils.getShortName(valueClass);
valueClass = ResolvableType.forMethodReturnType(method).getGeneric().resolve(Object.class); valueClass = ResolvableType.forMethodReturnType(method).getGeneric().toClass();
} }
} }
} }

View File

@ -229,7 +229,7 @@ public final class GenericTypeResolver {
*/ */
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public static Class<?> resolveType(Type genericType, Map<TypeVariable, Type> map) { public static Class<?> resolveType(Type genericType, Map<TypeVariable, Type> map) {
return ResolvableType.forType(genericType, new TypeVariableMapVariableResolver(map)).resolve(Object.class); return ResolvableType.forType(genericType, new TypeVariableMapVariableResolver(map)).toClass();
} }
/** /**

View File

@ -229,6 +229,18 @@ public class ResolvableType implements Serializable {
return (source != null ? source : this.type); return (source != null ? source : this.type);
} }
/**
* Return this type as a resolved {@code Class}, falling back to
* {@link java.lang.Object} if no specific class can be resolved.
* @return the resolved {@link Class} or the {@code Object} fallback
* @since 5.1
* @see #getRawClass()
* @see #resolve(Class)
*/
public Class<?> toClass() {
return resolve(Object.class);
}
/** /**
* Determine whether the given object is an instance of this {@code ResolvableType}. * Determine whether the given object is an instance of this {@code ResolvableType}.
* @param obj the object to check * @param obj the object to check
@ -328,7 +340,7 @@ public class ResolvableType implements Serializable {
if (ourResolved == null) { if (ourResolved == null) {
ourResolved = resolve(Object.class); ourResolved = resolve(Object.class);
} }
Class<?> otherResolved = other.resolve(Object.class); Class<?> otherResolved = other.toClass();
// We need an exact type match for generics // We need an exact type match for generics
// List<CharSequence> is not assignable from List<String> // List<CharSequence> is not assignable from List<String>

View File

@ -43,7 +43,7 @@ public class ByteArrayEncoder extends AbstractEncoder<byte[]> {
@Override @Override
public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) { public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) {
Class<?> clazz = elementType.resolve(Object.class); Class<?> clazz = elementType.toClass();
return super.canEncode(elementType, mimeType) && byte[].class.isAssignableFrom(clazz); return super.canEncode(elementType, mimeType) && byte[].class.isAssignableFrom(clazz);
} }

View File

@ -44,7 +44,7 @@ public class ByteBufferEncoder extends AbstractEncoder<ByteBuffer> {
@Override @Override
public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) { public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) {
Class<?> clazz = elementType.resolve(Object.class); Class<?> clazz = elementType.toClass();
return super.canEncode(elementType, mimeType) && ByteBuffer.class.isAssignableFrom(clazz); return super.canEncode(elementType, mimeType) && ByteBuffer.class.isAssignableFrom(clazz);
} }

View File

@ -56,7 +56,7 @@ public final class CharSequenceEncoder extends AbstractEncoder<CharSequence> {
@Override @Override
public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) { public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) {
Class<?> clazz = elementType.resolve(Object.class); Class<?> clazz = elementType.toClass();
return super.canEncode(elementType, mimeType) && CharSequence.class.isAssignableFrom(clazz); return super.canEncode(elementType, mimeType) && CharSequence.class.isAssignableFrom(clazz);
} }

View File

@ -43,7 +43,7 @@ public class DataBufferEncoder extends AbstractEncoder<DataBuffer> {
@Override @Override
public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) { public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) {
Class<?> clazz = elementType.resolve(Object.class); Class<?> clazz = elementType.toClass();
return super.canEncode(elementType, mimeType) && DataBuffer.class.isAssignableFrom(clazz); return super.canEncode(elementType, mimeType) && DataBuffer.class.isAssignableFrom(clazz);
} }

View File

@ -60,7 +60,7 @@ public class ResourceEncoder extends AbstractSingleValueEncoder<Resource> {
@Override @Override
public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) { public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) {
Class<?> clazz = elementType.resolve(Object.class); Class<?> clazz = elementType.toClass();
return (super.canEncode(elementType, mimeType) && Resource.class.isAssignableFrom(clazz)); return (super.canEncode(elementType, mimeType) && Resource.class.isAssignableFrom(clazz));
} }

View File

@ -73,7 +73,7 @@ public class ResourceRegionEncoder extends AbstractEncoder<ResourceRegion> {
@Override @Override
public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) { public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) {
return super.canEncode(elementType, mimeType) return super.canEncode(elementType, mimeType)
&& ResourceRegion.class.isAssignableFrom(elementType.resolve(Object.class)); && ResourceRegion.class.isAssignableFrom(elementType.toClass());
} }
@Override @Override

View File

@ -120,7 +120,7 @@ public class TypeDescriptor implements Serializable {
*/ */
protected TypeDescriptor(ResolvableType resolvableType, @Nullable Class<?> type, @Nullable Annotation[] annotations) { protected TypeDescriptor(ResolvableType resolvableType, @Nullable Class<?> type, @Nullable Annotation[] annotations) {
this.resolvableType = resolvableType; this.resolvableType = resolvableType;
this.type = (type != null ? type : resolvableType.resolve(Object.class)); this.type = (type != null ? type : resolvableType.toClass());
this.annotatedElement = new AnnotatedElementAdapter(annotations); this.annotatedElement = new AnnotatedElementAdapter(annotations);
} }

View File

@ -117,7 +117,7 @@ public class GenericConversionService implements ConfigurableConversionService {
"ConverterFactory [" + factory.getClass().getName() + "]; does the class parameterize those types?"); "ConverterFactory [" + factory.getClass().getName() + "]; does the class parameterize those types?");
} }
addConverter(new ConverterFactoryAdapter(factory, addConverter(new ConverterFactoryAdapter(factory,
new ConvertiblePair(typeInfo[0].resolve(Object.class), typeInfo[1].resolve(Object.class)))); new ConvertiblePair(typeInfo[0].toClass(), typeInfo[1].toClass())));
} }
@Override @Override
@ -351,7 +351,7 @@ public class GenericConversionService implements ConfigurableConversionService {
public ConverterAdapter(Converter<?, ?> converter, ResolvableType sourceType, ResolvableType targetType) { public ConverterAdapter(Converter<?, ?> converter, ResolvableType sourceType, ResolvableType targetType) {
this.converter = (Converter<Object, Object>) converter; this.converter = (Converter<Object, Object>) converter;
this.typeInfo = new ConvertiblePair(sourceType.resolve(Object.class), targetType.resolve(Object.class)); this.typeInfo = new ConvertiblePair(sourceType.toClass(), targetType.toClass());
this.targetType = targetType; this.targetType = targetType;
} }

View File

@ -619,7 +619,7 @@ public class ResolvableTypeTests {
ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray")); ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray"));
assertThat(type.getType().toString(), equalTo("T[]")); assertThat(type.getType().toString(), equalTo("T[]"));
assertThat(type.isArray(), equalTo(true)); assertThat(type.isArray(), equalTo(true));
assertThat(type.resolve(Object.class), equalTo((Class) Object.class)); assertThat(type.toClass(), equalTo((Class) Object.class));
} }
@Test @Test

View File

@ -97,7 +97,7 @@ public class MessageMethodArgumentResolver implements HandlerMethodArgumentResol
private Class<?> getPayloadType(MethodParameter parameter) { private Class<?> getPayloadType(MethodParameter parameter) {
Type genericParamType = parameter.getGenericParameterType(); Type genericParamType = parameter.getGenericParameterType();
ResolvableType resolvableType = ResolvableType.forType(genericParamType).as(Message.class); ResolvableType resolvableType = ResolvableType.forType(genericParamType).as(Message.class);
return resolvableType.getGeneric().resolve(Object.class); return resolvableType.getGeneric().toClass();
} }
/** /**

View File

@ -282,7 +282,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
return this.returnValue.getClass(); return this.returnValue.getClass();
} }
if (!ResolvableType.NONE.equals(this.returnType)) { if (!ResolvableType.NONE.equals(this.returnType)) {
return this.returnType.resolve(Object.class); return this.returnType.toClass();
} }
return super.getParameterType(); return super.getParameterType();
} }

View File

@ -84,7 +84,7 @@ public class FormHttpMessageReader extends LoggingCodecSupport
public boolean canRead(ResolvableType elementType, @Nullable MediaType mediaType) { public boolean canRead(ResolvableType elementType, @Nullable MediaType mediaType) {
return ((MULTIVALUE_TYPE.isAssignableFrom(elementType) || return ((MULTIVALUE_TYPE.isAssignableFrom(elementType) ||
(elementType.hasUnresolvableGenerics() && (elementType.hasUnresolvableGenerics() &&
MultiValueMap.class.isAssignableFrom(elementType.resolve(Object.class)))) && MultiValueMap.class.isAssignableFrom(elementType.toClass()))) &&
(mediaType == null || MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(mediaType))); (mediaType == null || MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(mediaType)));
} }

View File

@ -93,7 +93,7 @@ public class ServerSentEventHttpMessageWriter implements HttpMessageWriter<Objec
@Override @Override
public boolean canWrite(ResolvableType elementType, @Nullable MediaType mediaType) { public boolean canWrite(ResolvableType elementType, @Nullable MediaType mediaType) {
return (mediaType == null || MediaType.TEXT_EVENT_STREAM.includes(mediaType) || return (mediaType == null || MediaType.TEXT_EVENT_STREAM.includes(mediaType) ||
ServerSentEvent.class.isAssignableFrom(elementType.resolve(Object.class))); ServerSentEvent.class.isAssignableFrom(elementType.toClass()));
} }
@Override @Override

View File

@ -68,7 +68,7 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple
public boolean canDecode(ResolvableType elementType, @Nullable MimeType mimeType) { public boolean canDecode(ResolvableType elementType, @Nullable MimeType mimeType) {
JavaType javaType = getObjectMapper().getTypeFactory().constructType(elementType.getType()); JavaType javaType = getObjectMapper().getTypeFactory().constructType(elementType.getType());
// Skip String: CharSequenceDecoder + "*/*" comes after // Skip String: CharSequenceDecoder + "*/*" comes after
return (!CharSequence.class.isAssignableFrom(elementType.resolve(Object.class)) && return (!CharSequence.class.isAssignableFrom(elementType.toClass()) &&
getObjectMapper().canDeserialize(javaType) && supportsMimeType(mimeType)); getObjectMapper().canDeserialize(javaType) && supportsMimeType(mimeType));
} }

View File

@ -100,7 +100,7 @@ public abstract class AbstractJackson2Encoder extends Jackson2CodecSupport imple
@Override @Override
public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) { public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) {
Class<?> clazz = elementType.resolve(Object.class); Class<?> clazz = elementType.toClass();
return supportsMimeType(mimeType) && (Object.class == clazz || return supportsMimeType(mimeType) && (Object.class == clazz ||
(!String.class.isAssignableFrom(elementType.resolve(clazz)) && getObjectMapper().canSerialize(clazz))); (!String.class.isAssignableFrom(elementType.resolve(clazz)) && getObjectMapper().canSerialize(clazz)));
} }

View File

@ -86,7 +86,7 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem
@Override @Override
public boolean canRead(ResolvableType elementType, @Nullable MediaType mediaType) { public boolean canRead(ResolvableType elementType, @Nullable MediaType mediaType) {
return Part.class.equals(elementType.resolve(Object.class)) && return Part.class.equals(elementType.toClass()) &&
(mediaType == null || MediaType.MULTIPART_FORM_DATA.isCompatibleWith(mediaType)); (mediaType == null || MediaType.MULTIPART_FORM_DATA.isCompatibleWith(mediaType));
} }

View File

@ -60,7 +60,7 @@ public class Jaxb2XmlEncoder extends AbstractSingleValueEncoder<Object> {
@Override @Override
public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) { public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) {
if (super.canEncode(elementType, mimeType)) { if (super.canEncode(elementType, mimeType)) {
Class<?> outputClass = elementType.resolve(Object.class); Class<?> outputClass = elementType.toClass();
return (outputClass.isAnnotationPresent(XmlRootElement.class) || return (outputClass.isAnnotationPresent(XmlRootElement.class) ||
outputClass.isAnnotationPresent(XmlType.class)); outputClass.isAnnotationPresent(XmlType.class));
} }

View File

@ -89,7 +89,7 @@ public class ResponseEntityResultHandler extends AbstractMessageWriterResultHand
} }
ReactiveAdapter adapter = getAdapter(result); ReactiveAdapter adapter = getAdapter(result);
return adapter != null && !adapter.isNoValue() && return adapter != null && !adapter.isNoValue() &&
isSupportedType(result.getReturnType().getGeneric().resolve(Object.class)); isSupportedType(result.getReturnType().getGeneric().toClass());
} }
@Nullable @Nullable

View File

@ -157,7 +157,7 @@ public class ViewResolutionResultHandler extends HandlerResultHandlerSupport
if (adapter.isNoValue()) { if (adapter.isNoValue()) {
return true; return true;
} }
type = result.getReturnType().getGeneric().resolve(Object.class); type = result.getReturnType().getGeneric().toClass();
} }
return (type != null && return (type != null &&

View File

@ -288,7 +288,7 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro
else { else {
Type type = getHttpEntityType(returnType); Type type = getHttpEntityType(returnType);
type = (type != null ? type : Object.class); type = (type != null ? type : Object.class);
return ResolvableType.forMethodParameter(returnType, type).resolve(Object.class); return ResolvableType.forMethodParameter(returnType, type).toClass();
} }
} }

View File

@ -123,7 +123,7 @@ class ReactiveTypeHandler {
Assert.state(adapter != null, "Unexpected return value: " + returnValue); Assert.state(adapter != null, "Unexpected return value: " + returnValue);
ResolvableType elementType = ResolvableType.forMethodParameter(returnType).getGeneric(); ResolvableType elementType = ResolvableType.forMethodParameter(returnType).getGeneric();
Class<?> elementClass = elementType.resolve(Object.class); Class<?> elementClass = elementType.toClass();
Collection<MediaType> mediaTypes = getMediaTypes(request); Collection<MediaType> mediaTypes = getMediaTypes(request);
Optional<MediaType> mediaType = mediaTypes.stream().filter(MimeType::isConcrete).findFirst(); Optional<MediaType> mediaType = mediaTypes.stream().filter(MimeType::isConcrete).findFirst();

View File

@ -271,7 +271,7 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
return this.returnValue.getClass(); return this.returnValue.getClass();
} }
if (!ResolvableType.NONE.equals(this.returnType)) { if (!ResolvableType.NONE.equals(this.returnType)) {
return this.returnType.resolve(Object.class); return this.returnType.toClass();
} }
return super.getParameterType(); return super.getParameterType();
} }