Browse Source

ResolvableType.getType() returns ParameterizedType when built with forClassWithGenerics

Issue: SPR-12701
pull/703/merge
Juergen Hoeller 11 years ago
parent
commit
91a0107e4a
  1. 55
      spring-core/src/main/java/org/springframework/core/ResolvableType.java
  2. 13
      spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java

55
spring-core/src/main/java/org/springframework/core/ResolvableType.java

@ -1131,11 +1131,21 @@ public final class ResolvableType implements Serializable { @@ -1131,11 +1131,21 @@ public final class ResolvableType implements Serializable {
* @return a {@link ResolvableType} for the specific class and generics
* @see #forClassWithGenerics(Class, Class...)
*/
public static ResolvableType forClassWithGenerics(Class<?> sourceClass, ResolvableType... generics) {
public static ResolvableType forClassWithGenerics(final Class<?> sourceClass, final ResolvableType... generics) {
Assert.notNull(sourceClass, "Source class must not be null");
Assert.notNull(generics, "Generics must not be null");
TypeVariable<?>[] typeVariables = sourceClass.getTypeParameters();
return forType(sourceClass, new TypeVariablesVariableResolver(typeVariables, generics));
TypeVariable<?>[] variables = sourceClass.getTypeParameters();
Assert.isTrue(variables.length == generics.length, "Mismatched number of generics specified");
Type[] arguments = new Type[generics.length];
for (int i = 0; i < generics.length; i++) {
ResolvableType generic = generics[i];
Type argument = (generic != null ? generic.getType() : null);
arguments[i] = (argument != null ? argument : variables[i]);
}
ParameterizedType syntheticType = new SyntheticParameterizedType(sourceClass, arguments);
return forType(syntheticType, new TypeVariablesVariableResolver(variables, generics));
}
/**
@ -1249,20 +1259,19 @@ public final class ResolvableType implements Serializable { @@ -1249,20 +1259,19 @@ public final class ResolvableType implements Serializable {
@SuppressWarnings("serial")
private static class TypeVariablesVariableResolver implements VariableResolver {
private final TypeVariable<?>[] typeVariables;
private final TypeVariable<?>[] variables;
private final ResolvableType[] generics;
public TypeVariablesVariableResolver(TypeVariable<?>[] typeVariables, ResolvableType[] generics) {
Assert.isTrue(typeVariables.length == generics.length, "Mismatched number of generics specified");
this.typeVariables = typeVariables;
public TypeVariablesVariableResolver(TypeVariable<?>[] variables, ResolvableType[] generics) {
this.variables = variables;
this.generics = generics;
}
@Override
public ResolvableType resolveVariable(TypeVariable<?> variable) {
for (int i = 0; i < this.typeVariables.length; i++) {
if (SerializableTypeWrapper.unwrap(this.typeVariables[i]).equals(
for (int i = 0; i < this.variables.length; i++) {
if (SerializableTypeWrapper.unwrap(this.variables[i]).equals(
SerializableTypeWrapper.unwrap(variable))) {
return this.generics[i];
}
@ -1277,6 +1286,34 @@ public final class ResolvableType implements Serializable { @@ -1277,6 +1286,34 @@ public final class ResolvableType implements Serializable {
}
private static final class SyntheticParameterizedType implements ParameterizedType, Serializable {
private final Type rawType;
private final Type[] typeArguments;
public SyntheticParameterizedType(Type rawType, Type[] typeArguments) {
this.rawType = rawType;
this.typeArguments = typeArguments;
}
@Override
public Type[] getActualTypeArguments() {
return this.typeArguments;
}
@Override
public Type getRawType() {
return this.rawType;
}
@Override
public Type getOwnerType() {
return null;
}
}
/**
* Internal helper to handle bounds from {@link WildcardType}s.
*/

13
spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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 java.util.List; @@ -39,6 +39,7 @@ import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import org.hamcrest.Matchers;
import org.junit.Rule;
@ -1210,6 +1211,16 @@ public class ResolvableTypeTests { @@ -1210,6 +1211,16 @@ public class ResolvableTypeTests {
assertEquals("java.util.Collection<org.springframework.core.ResolvableTypeTests$IBase<?>>", type.toString());
}
@Test
public void testSpr12701() throws Exception {
ResolvableType resolvableType = ResolvableType.forClassWithGenerics(Callable.class, String.class);
Type type = resolvableType.getType();
assertThat(type, is(instanceOf(ParameterizedType.class)));
assertThat(((ParameterizedType) type).getRawType(), is(equalTo(Callable.class)));
assertThat(((ParameterizedType) type).getActualTypeArguments().length, is(equalTo(1)));
assertThat(((ParameterizedType) type).getActualTypeArguments()[0], is(equalTo(String.class)));
}
private ResolvableType testSerialization(ResolvableType type) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();

Loading…
Cancel
Save