Polish ResolvableType & SerializableTypeWrapper
Fix 'missing serialVersionUID' warnings, support for void.class types and refine resolve() algorithm to support narrowed types. Issue: SPR-10973
This commit is contained in:
parent
f4a66a4326
commit
f29092db23
|
@ -72,6 +72,9 @@ import org.springframework.util.StringUtils;
|
|||
*/
|
||||
public final class ResolvableType implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private static ConcurrentReferenceHashMap<ResolvableType, ResolvableType> cache =
|
||||
new ConcurrentReferenceHashMap<ResolvableType, ResolvableType>();
|
||||
|
||||
|
@ -97,8 +100,13 @@ public final class ResolvableType implements Serializable {
|
|||
private final VariableResolver variableResolver;
|
||||
|
||||
/**
|
||||
* Stored copy of the resolved value or {@code null} if the resolve method has not
|
||||
* yet been called. {@code void.class} is used when the resolve method failed.
|
||||
* If resolution has happened and {@link #resolved} contains a valid result.
|
||||
*/
|
||||
private boolean isResolved = false;
|
||||
|
||||
/**
|
||||
* Late binding stored copy of the resolved value (valid when {@link #isResolved} is
|
||||
* true).
|
||||
*/
|
||||
private Class<?> resolved;
|
||||
|
||||
|
@ -484,11 +492,11 @@ public final class ResolvableType implements Serializable {
|
|||
* @see #resolveGenerics()
|
||||
*/
|
||||
public Class<?> resolve(Class<?> fallback) {
|
||||
if (this.resolved == null) {
|
||||
Class<?> resolvedClass = resolveClass();
|
||||
this.resolved = (resolvedClass == null ? void.class : resolvedClass);
|
||||
if (!this.isResolved) {
|
||||
this.resolved = resolveClass();
|
||||
this.isResolved = true;
|
||||
}
|
||||
return (this.resolved == void.class ? fallback : this.resolved);
|
||||
return (this.resolved == null ? fallback : this.resolved);
|
||||
}
|
||||
|
||||
private Class<?> resolveClass() {
|
||||
|
@ -553,15 +561,12 @@ public final class ResolvableType implements Serializable {
|
|||
}
|
||||
|
||||
if (this.type instanceof ParameterizedType) {
|
||||
|
||||
ParameterizedType parameterizedType = (ParameterizedType) this.type;
|
||||
if (parameterizedType.getRawType().equals(variable.getGenericDeclaration())) {
|
||||
TypeVariable<?>[] variables = resolve().getTypeParameters();
|
||||
for (int i = 0; i < variables.length; i++) {
|
||||
if (ObjectUtils.nullSafeEquals(variables[i].getName(), variable.getName())) {
|
||||
Type actualType = parameterizedType.getActualTypeArguments()[i];
|
||||
return forType(actualType, this.variableResolver);
|
||||
}
|
||||
TypeVariable<?>[] variables = resolve().getTypeParameters();
|
||||
for (int i = 0; i < variables.length; i++) {
|
||||
if (ObjectUtils.nullSafeEquals(variables[i].getName(), variable.getName())) {
|
||||
Type actualType = parameterizedType.getActualTypeArguments()[i];
|
||||
return forType(actualType, this.variableResolver);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -637,6 +642,10 @@ public final class ResolvableType implements Serializable {
|
|||
}
|
||||
|
||||
return new VariableResolver() {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@Override
|
||||
public ResolvableType resolveVariable(TypeVariable<?> variable) {
|
||||
return ResolvableType.this.resolveVariable(variable);
|
||||
|
@ -901,7 +910,13 @@ public final class ResolvableType implements Serializable {
|
|||
final TypeVariable<?>[] typeVariables = sourceClass.getTypeParameters();
|
||||
Assert.isTrue(typeVariables.length == generics.length,
|
||||
"Missmatched number of generics specified");
|
||||
|
||||
|
||||
VariableResolver variableResolver = new VariableResolver() {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@Override
|
||||
public ResolvableType resolveVariable(TypeVariable<?> variable) {
|
||||
for (int i = 0; i < typeVariables.length; i++) {
|
||||
|
|
|
@ -78,6 +78,10 @@ abstract class SerializableTypeWrapper {
|
|||
*/
|
||||
public static Type forGenericSuperclass(final Class<?> type) {
|
||||
return forTypeProvider(new TypeProvider() {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type.getGenericSuperclass();
|
||||
|
@ -93,6 +97,10 @@ abstract class SerializableTypeWrapper {
|
|||
for (int i = 0; i < result.length; i++) {
|
||||
final int index = i;
|
||||
result[i] = forTypeProvider(new TypeProvider() {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type.getGenericInterfaces()[index];
|
||||
|
@ -110,6 +118,10 @@ abstract class SerializableTypeWrapper {
|
|||
for (int i = 0; i < result.length; i++) {
|
||||
final int index = i;
|
||||
result[i] = forTypeProvider(new TypeProvider() {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return type.getTypeParameters()[index];
|
||||
|
@ -162,6 +174,9 @@ abstract class SerializableTypeWrapper {
|
|||
private static class TypeProxyInvocationHandler implements InvocationHandler,
|
||||
Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private final TypeProvider provider;
|
||||
|
||||
|
||||
|
@ -194,6 +209,9 @@ abstract class SerializableTypeWrapper {
|
|||
*/
|
||||
private static class FieldTypeProvider implements TypeProvider {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private final String fieldName;
|
||||
|
||||
private final Class<?> declaringClass;
|
||||
|
@ -233,6 +251,9 @@ abstract class SerializableTypeWrapper {
|
|||
*/
|
||||
private static class MethodParameterTypeProvider implements TypeProvider {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private final String methodName;
|
||||
|
||||
private final Class<?>[] parameterTypes;
|
||||
|
@ -293,6 +314,9 @@ abstract class SerializableTypeWrapper {
|
|||
*/
|
||||
private static class MethodInvokeTypeProvider implements TypeProvider {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private final TypeProvider provider;
|
||||
|
||||
private final String methodName;
|
||||
|
|
|
@ -52,7 +52,6 @@ import org.springframework.core.ResolvableType.VariableResolver;
|
|||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import static org.mockito.BDDMockito.*;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
@ -1097,6 +1096,20 @@ public class ResolvableTypeTests {
|
|||
assertThat(deserializedNone, sameInstance(ResolvableType.NONE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canResolveVoid() throws Exception {
|
||||
ResolvableType type = ResolvableType.forClass(void.class);
|
||||
assertThat(type.resolve(), equalTo((Class) void.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void narrow() throws Exception {
|
||||
ResolvableType type = ResolvableType.forField(Fields.class.getField("stringList"));
|
||||
ResolvableType narrow = ResolvableType.forType(ArrayList.class, type);
|
||||
assertThat(narrow.getGeneric().resolve(), equalTo((Class) String.class));
|
||||
}
|
||||
|
||||
|
||||
private ResolvableType testSerialization(ResolvableType type) throws Exception {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(bos);
|
||||
|
|
Loading…
Reference in New Issue