Skip to content

Commit 9076c70

Browse files
author
Phillip Webb
committed
Provide 'with implementationType' overloads
Provided overloaded versions of `forField` and `forMethodParameter` that accept a `ResolvableType` implementation type (as opposed to a Class). Primarily added to allow resolution against implementation types that have been created programmatically using `forTypeWithGenerics`. Issue: SPR-11218
1 parent 7e6dbc2 commit 9076c70

File tree

2 files changed

+58
-3
lines changed

2 files changed

+58
-3
lines changed

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

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -835,6 +835,23 @@ public static ResolvableType forField(Field field, Class<?> implementationClass)
835835
return forType(null, new FieldTypeProvider(field), owner.asVariableResolver());
836836
}
837837

838+
/**
839+
* Return a {@link ResolvableType} for the specified {@link Field} with a given
840+
* implementation.
841+
* <p>Use this variant when the class that declares the field includes generic
842+
* parameter variables that are satisfied by the implementation type.
843+
* @param field the source field
844+
* @param implementationType the implementation type
845+
* @return a {@link ResolvableType} for the specified field
846+
* @see #forField(Field)
847+
*/
848+
public static ResolvableType forField(Field field, ResolvableType implementationType) {
849+
Assert.notNull(field, "Field must not be null");
850+
implementationType = (implementationType == null ? NONE : implementationType);
851+
ResolvableType owner = implementationType.as(field.getDeclaringClass());
852+
return forType(null, new FieldTypeProvider(field), owner.asVariableResolver());
853+
}
854+
838855
/**
839856
* Return a {@link ResolvableType} for the specified {@link Field} with the
840857
* given nesting level.
@@ -963,7 +980,25 @@ public static ResolvableType forMethodParameter(Method method, int parameterInde
963980
* @see #forMethodParameter(Method, int)
964981
*/
965982
public static ResolvableType forMethodParameter(MethodParameter methodParameter) {
966-
return forMethodParameter(methodParameter, null);
983+
return forMethodParameter(methodParameter, (Type) null);
984+
}
985+
986+
/**
987+
* Return a {@link ResolvableType} for the specified {@link MethodParameter} with a
988+
* given implementation type. Use this variant when the class that declares the method
989+
* includes generic parameter variables that are satisfied by the implementation type.
990+
* @param methodParameter the source method parameter (must not be {@code null})
991+
* @param implementationType the implementation type
992+
* @return a {@link ResolvableType} for the specified method parameter
993+
* @see #forMethodParameter(MethodParameter)
994+
*/
995+
public static ResolvableType forMethodParameter(MethodParameter methodParameter, ResolvableType implementationType) {
996+
Assert.notNull(methodParameter, "MethodParameter must not be null");
997+
implementationType = (implementationType == null ? forType(methodParameter.getContainingClass()) : implementationType);
998+
ResolvableType owner = implementationType.as(methodParameter.getDeclaringClass());
999+
return forType(null, new MethodParameterTypeProvider(methodParameter),
1000+
owner.asVariableResolver()).getNested(methodParameter.getNestingLevel(),
1001+
methodParameter.typeIndexesPerLevel);
9671002
}
9681003

9691004
/**

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -659,6 +659,16 @@ public void resolveTypeVariableFromFieldTypeWithImplementsClass() throws Excepti
659659
assertThat(type.getGeneric().resolve(), equalTo((Class) String.class));
660660
}
661661

662+
@Test
663+
public void resolveTypeVariableFromFieldTypeWithImplementsType() throws Exception {
664+
ResolvableType implementationType = ResolvableType.forClassWithGenerics(
665+
Fields.class, Integer.class);
666+
ResolvableType type = ResolvableType.forField(
667+
Fields.class.getField("parameterizedType"), implementationType);
668+
assertThat(type.resolve(), equalTo((Class) List.class));
669+
assertThat(type.getGeneric().resolve(), equalTo((Class) Integer.class));
670+
}
671+
662672
@Test
663673
public void resolveTypeVariableFromSuperType() throws Exception {
664674
ResolvableType type = ResolvableType.forClass(ExtendsList.class);
@@ -735,6 +745,16 @@ public void resolveTypeVariableFromMethodParameterTypeWithImplementsClass() thro
735745
assertThat(type.getType().toString(), equalTo("T"));
736746
}
737747

748+
@Test
749+
public void resolveTypeVariableFromMethodParameterTypeWithImplementsType() throws Exception {
750+
Method method = Methods.class.getMethod("typedParameter", Object.class);
751+
MethodParameter methodParameter = MethodParameter.forMethodOrConstructor(method, 0);
752+
ResolvableType implementationType = ResolvableType.forClassWithGenerics(Methods.class, Integer.class);
753+
ResolvableType type = ResolvableType.forMethodParameter(methodParameter, implementationType);
754+
assertThat(type.resolve(), equalTo((Class) Integer.class));
755+
assertThat(type.getType().toString(), equalTo("T"));
756+
}
757+
738758
@Test
739759
public void resolveTypeVariableFromMethodReturn() throws Exception {
740760
Method method = Methods.class.getMethod("typedReturn");

0 commit comments

Comments
 (0)