前言
在JDK原生類庫里面,Type總共有5種類型,分別是:原始類型、參數(shù)化類型、泛型數(shù)組類型、類型變量和通配符類型。這些類型相互間串起來操作的時候,就會出現(xiàn)一些問題。例如:
- 代碼重復(fù)和繁長;
- 對JDK的Type不熟悉的話,也容易出錯。
而壞味道的代碼,總是容易讓一些有潔癖的人無法忍受,并最終處理掉。最終,Spring里面的ResolvableType在Type的基礎(chǔ)上,封裝了我們常用的一些操作,使得我們對Java類型的操作變得更加簡單。
我們來看看ResolvableType提供的 javadoc文檔,其描述信息如下:
/**
* Encapsulates a Java {@link java.lang.reflect.Type}, providing access to
* {@link #getSuperType() supertypes}, {@link #getInterfaces() interfaces}, and
* {@link #getGeneric(int...) generic parameters} along with the ability to ultimately
* {@link #resolve() resolve} to a {@link java.lang.Class}.
*
* <p>{@code ResolvableTypes} may be obtained from {@link #forField(Field) fields},
* {@link #forMethodParameter(Method, int) method parameters},
* {@link #forMethodReturnType(Method) method returns} or
* {@link #forClass(Class) classes}. Most methods on this class will themselves return
* {@link ResolvableType ResolvableTypes}, allowing easy navigation. For example:
* <pre class="code">
* private HashMap<Integer, List<String>> myMap;
*
* public void example() {
* ResolvableType t = ResolvableType.forField(getClass().getDeclaredField("myMap"));
* t.getSuperType(); // AbstractMap<Integer, List<String>>
* t.asMap(); // Map<Integer, List<String>>
* t.getGeneric(0).resolve(); // Integer
* t.getGeneric(1).resolve(); // List
* t.getGeneric(1); // List<String>
* t.resolveGeneric(1, 0); // String
* }
* </pre>
*/
中文翻譯如下:
ResolvableType是對Java類型的封裝,提供了對父類(getSuperType())、接口(getInterfaces())、泛型參數(shù)(getGeneric(int...))的訪問,最底層的實(shí)現(xiàn)為resolve()方法。
ResolvableType可以通過forField(Field)、forMethodParameter(Method, int)、forMethodReturnType(Method)和forClass(Class)進(jìn)行構(gòu)造。這個類的大部分方法返回的都是ResolvableType類型,同時允許用戶很容易地進(jìn)行導(dǎo)航操作。例如:
private HashMap<Integer, List<String>> myMap;
public void example() {
ResolvableType t = ResolvableType.forField(getClass().getDeclaredField("myMap"));
t.getSuperType(); // AbstractMap<Integer, List<String>>
t.asMap(); // Map<Integer, List<String>>
t.getGeneric(0).resolve(); // Integer
t.getGeneric(1).resolve(); // List
t.getGeneric(1); // List<String>
t.resolveGeneric(1, 0); // String
}
源碼解析
構(gòu)造方法
/**
* Private constructor used to create a new {@link ResolvableType} for cache key purposes,
* with no upfront resolution.
*/
private ResolvableType(
Type type, @Nullable TypeProvider typeProvider, @Nullable VariableResolver variableResolver) {
this.type = type;
this.typeProvider = typeProvider;
this.variableResolver = variableResolver;
this.componentType = null;
this.hash = calculateHashCode();
this.resolved = null;
}
/**
* Private constructor used to create a new {@link ResolvableType} for cache value purposes,
* with upfront resolution and a pre-calculated hash.
* @since 4.2
*/
private ResolvableType(Type type, @Nullable TypeProvider typeProvider,
@Nullable VariableResolver variableResolver, @Nullable Integer hash) {
this.type = type;
this.typeProvider = typeProvider;
this.variableResolver = variableResolver;
this.componentType = null;
this.hash = hash;
this.resolved = resolveClass();
}
/**
* Private constructor used to create a new {@link ResolvableType} for uncached purposes,
* with upfront resolution but lazily calculated hash.
*/
private ResolvableType(Type type, @Nullable TypeProvider typeProvider,
@Nullable VariableResolver variableResolver, @Nullable ResolvableType componentType) {
this.type = type;
this.typeProvider = typeProvider;
this.variableResolver = variableResolver;
this.componentType = componentType;
this.hash = null;
this.resolved = resolveClass();
}
/**
* Private constructor used to create a new {@link ResolvableType} on a {@link Class} basis.
* Avoids all {@code instanceof} checks in order to create a straight {@link Class} wrapper.
* @since 4.2
*/
private ResolvableType(@Nullable Class<?> clazz) {
this.resolved = (clazz != null ? clazz : Object.class);
this.type = this.resolved;
this.typeProvider = null;
this.variableResolver = null;
this.componentType = null;
this.hash = null;
}
從源碼看,所有的構(gòu)造方法都是私有的。因此,我們不能直接通過構(gòu)造方法創(chuàng)建實(shí)例。
這些構(gòu)造方法,絕大多數(shù)操作都只是賦值。唯一有點(diǎn)區(qū)別的地方在于,當(dāng)hash或者componentType參數(shù)有傳入的時候,會調(diào)用resolveClass()方法進(jìn)行類處理操作。
forClass
forClass用于通過Class類型的對象構(gòu)造ResolvableType類型。
public static ResolvableType forClass(@Nullable Class<?> clazz) {
return new ResolvableType(clazz);
}
很簡單,調(diào)用私有構(gòu)造方法直接就構(gòu)建了。
public static ResolvableType forRawClass(@Nullable Class<?> clazz) {
return new ResolvableType(clazz) {
@Override
public ResolvableType[] getGenerics() {
return EMPTY_TYPES_ARRAY;
}
@Override
public boolean isAssignableFrom(Class<?> other) {
return (clazz == null || ClassUtils.isAssignable(clazz, other));
}
@Override
public boolean isAssignableFrom(ResolvableType other) {
Class<?> otherClass = other.resolve();
return (otherClass != null && (clazz == null || ClassUtils.isAssignable(clazz, otherClass)));
}
};
}
和forClass(@Nullable Class<?> clazz)的邏輯基本相同,唯一的區(qū)別就是重寫了三個方法。這是為什么呢?原因在于:
- 對于基本數(shù)據(jù)類型來說,泛型參數(shù)的對象數(shù)組一定是空數(shù)組;
- 對于基本數(shù)據(jù)類型來說,繼承關(guān)系的比較邏輯是固定不變的。
/**
* Return a {@link ResolvableType} for the specified base type
* (interface or base class) with a given implementation class.
* For example: {@code ResolvableType.forClass(List.class, MyArrayList.class)}.
* @param baseType the base type (must not be {@code null})
* @param implementationClass the implementation class
* @return a {@link ResolvableType} for the specified base type backed by the
* given implementation class
* @see #forClass(Class)
* @see #forClassWithGenerics(Class, Class...)
*/
public static ResolvableType forClass(Class<?> baseType, Class<?> implementationClass) {
Assert.notNull(baseType, "Base type must not be null");
ResolvableType asType = forType(implementationClass).as(baseType);
return (asType == NONE ? forType(baseType) : asType);
}
implementationClass是baseType的子類,這個方法主要獲取baseType上定義的泛型。
public static ResolvableType forInstance(Object instance) {
Assert.notNull(instance, "Instance must not be null");
if (instance instanceof ResolvableTypeProvider) {
ResolvableType type = ((ResolvableTypeProvider) instance).getResolvableType();
if (type != null) {
return type;
}
}
return ResolvableType.forClass(instance.getClass());
}
底層調(diào)用的仍然是forClass()方法,只是在調(diào)用之前進(jìn)行了類型甄別和適配轉(zhuǎn)換。
forConstructorParameter
/**
* Return a {@link ResolvableType} for the specified {@link Constructor} parameter.
* @param constructor the source constructor (must not be {@code null})
* @param parameterIndex the parameter index
* @return a {@link ResolvableType} for the specified constructor parameter
* @see #forConstructorParameter(Constructor, int, Class)
*/
public static ResolvableType forConstructorParameter(Constructor<?> constructor, int parameterIndex) {
Assert.notNull(constructor, "Constructor must not be null");
return forMethodParameter(new MethodParameter(constructor, parameterIndex));
}
/**
* Return a {@link ResolvableType} for the specified {@link Constructor} parameter
* with a given implementation. Use this variant when the class that declares the
* constructor includes generic parameter variables that are satisfied by the
* implementation class.
* @param constructor the source constructor (must not be {@code null})
* @param parameterIndex the parameter index
* @param implementationClass the implementation class
* @return a {@link ResolvableType} for the specified constructor parameter
* @see #forConstructorParameter(Constructor, int)
*/
public static ResolvableType forConstructorParameter(Constructor<?> constructor, int parameterIndex,
Class<?> implementationClass) {
Assert.notNull(constructor, "Constructor must not be null");
MethodParameter methodParameter = new MethodParameter(constructor, parameterIndex, implementationClass);
return forMethodParameter(methodParameter);
}
構(gòu)造方法和普通方法大體相同,唯一區(qū)別在于,構(gòu)造方法沒有返回值。因此,forConstructorParameter()方法的底層調(diào)用仍然是forMethodParameter()方法。關(guān)于forMethodParameter()方法,我們稍后分析。
forField
/**
* 通過Field構(gòu)造,內(nèi)部是使用`FieldTypeProvider`來輔助轉(zhuǎn)換的。
* Return a {@link ResolvableType} for the specified {@link Field}.
* @param field the source field
* @return a {@link ResolvableType} for the specified field
* @see #forField(Field, Class)
*/
public static ResolvableType forField(Field field) {
Assert.notNull(field, "Field must not be null");
return forType(null, new FieldTypeProvider(field), null);
}
/**
* 同上,只是多了forType().as()的操作。
* Return a {@link ResolvableType} for the specified {@link Field} with a given
* implementation.
* <p>Use this variant when the class that declares the field includes generic
* parameter variables that are satisfied by the implementation class.
* @param field the source field
* @param implementationClass the implementation class
* @return a {@link ResolvableType} for the specified field
* @see #forField(Field)
*/
public static ResolvableType forField(Field field, Class<?> implementationClass) {
Assert.notNull(field, "Field must not be null");
ResolvableType owner = forType(implementationClass).as(field.getDeclaringClass());
return forType(null, new FieldTypeProvider(field), owner.asVariableResolver());
}
/**
* 同上,只是實(shí)現(xiàn)類型由Class變更為了ResolvableType
* Return a {@link ResolvableType} for the specified {@link Field} with a given
* implementation.
* <p>Use this variant when the class that declares the field includes generic
* parameter variables that are satisfied by the implementation type.
* @param field the source field
* @param implementationType the implementation type
* @return a {@link ResolvableType} for the specified field
* @see #forField(Field)
*/
public static ResolvableType forField(Field field, @Nullable ResolvableType implementationType) {
Assert.notNull(field, "Field must not be null");
ResolvableType owner = (implementationType != null ? implementationType : NONE);
owner = owner.as(field.getDeclaringClass());
return forType(null, new FieldTypeProvider(field), owner.asVariableResolver());
}
/**
* 同上,只是增加了嵌套級數(shù)。
* 例如:A<B<C>>。
* 1. 當(dāng)嵌套級數(shù)為1時,為B<C>;
* 2. 當(dāng)嵌套級數(shù)為2時,為C;
* 3. 當(dāng)嵌套級數(shù)為3時,為ResolvableType$EmptyType
* Return a {@link ResolvableType} for the specified {@link Field} with the
* given nesting level.
* @param field the source field
* @param nestingLevel the nesting level (1 for the outer level; 2 for a nested
* generic type; etc)
* @see #forField(Field)
*/
public static ResolvableType forField(Field field, int nestingLevel) {
Assert.notNull(field, "Field must not be null");
return forType(null, new FieldTypeProvider(field), null).getNested(nestingLevel);
}
/**
* 這是更底層的實(shí)現(xiàn),同時支持嵌套級數(shù)和實(shí)現(xiàn)類。
* Return a {@link ResolvableType} for the specified {@link Field} with a given
* implementation and the given nesting level.
* <p>Use this variant when the class that declares the field includes generic
* parameter variables that are satisfied by the implementation class.
* @param field the source field
* @param nestingLevel the nesting level (1 for the outer level; 2 for a nested
* generic type; etc)
* @param implementationClass the implementation class
* @return a {@link ResolvableType} for the specified field
* @see #forField(Field)
*/
public static ResolvableType forField(Field field, int nestingLevel, @Nullable Class<?> implementationClass) {
Assert.notNull(field, "Field must not be null");
ResolvableType owner = forType(implementationClass).as(field.getDeclaringClass());
return forType(null, new FieldTypeProvider(field), owner.asVariableResolver()).getNested(nestingLevel);
}
forMethodReturnType
/**
* Return a {@link ResolvableType} for the specified {@link Method} return type.
* @param method the source for the method return type
* @return a {@link ResolvableType} for the specified method return
* @see #forMethodReturnType(Method, Class)
*/
public static ResolvableType forMethodReturnType(Method method) {
Assert.notNull(method, "Method must not be null");
return forMethodParameter(new MethodParameter(method, -1));
}
/**
* Return a {@link ResolvableType} for the specified {@link Method} return type.
* Use this variant when the class that declares the method includes generic
* parameter variables that are satisfied by the implementation class.
* @param method the source for the method return type
* @param implementationClass the implementation class
* @return a {@link ResolvableType} for the specified method return
* @see #forMethodReturnType(Method)
*/
public static ResolvableType forMethodReturnType(Method method, Class<?> implementationClass) {
Assert.notNull(method, "Method must not be null");
MethodParameter methodParameter = new MethodParameter(method, -1, implementationClass);
return forMethodParameter(methodParameter);
}
最終調(diào)用的是forMethodParameter()方法,只是傳入的下標(biāo)為-1。
forMethodParameter
/**
* Return a {@link ResolvableType} for the specified {@link Method} parameter.
* @param method the source method (must not be {@code null})
* @param parameterIndex the parameter index
* @return a {@link ResolvableType} for the specified method parameter
* @see #forMethodParameter(Method, int, Class)
* @see #forMethodParameter(MethodParameter)
*/
public static ResolvableType forMethodParameter(Method method, int parameterIndex) {
Assert.notNull(method, "Method must not be null");
return forMethodParameter(new MethodParameter(method, parameterIndex));
}
/**
* Return a {@link ResolvableType} for the specified {@link Method} parameter with a
* given implementation. Use this variant when the class that declares the method
* includes generic parameter variables that are satisfied by the implementation class.
* @param method the source method (must not be {@code null})
* @param parameterIndex the parameter index
* @param implementationClass the implementation class
* @return a {@link ResolvableType} for the specified method parameter
* @see #forMethodParameter(Method, int, Class)
* @see #forMethodParameter(MethodParameter)
*/
public static ResolvableType forMethodParameter(Method method, int parameterIndex, Class<?> implementationClass) {
Assert.notNull(method, "Method must not be null");
MethodParameter methodParameter = new MethodParameter(method, parameterIndex, implementationClass);
return forMethodParameter(methodParameter);
}
/**
* Return a {@link ResolvableType} for the specified {@link MethodParameter}.
* @param methodParameter the source method parameter (must not be {@code null})
* @return a {@link ResolvableType} for the specified method parameter
* @see #forMethodParameter(Method, int)
*/
public static ResolvableType forMethodParameter(MethodParameter methodParameter) {
return forMethodParameter(methodParameter, (Type) null);
}
/**
* Return a {@link ResolvableType} for the specified {@link MethodParameter} with a
* given implementation type. Use this variant when the class that declares the method
* includes generic parameter variables that are satisfied by the implementation type.
* @param methodParameter the source method parameter (must not be {@code null})
* @param implementationType the implementation type
* @return a {@link ResolvableType} for the specified method parameter
* @see #forMethodParameter(MethodParameter)
*/
public static ResolvableType forMethodParameter(MethodParameter methodParameter,
@Nullable ResolvableType implementationType) {
Assert.notNull(methodParameter, "MethodParameter must not be null");
implementationType = (implementationType != null ? implementationType :
forType(methodParameter.getContainingClass()));
ResolvableType owner = implementationType.as(methodParameter.getDeclaringClass());
return forType(null, new MethodParameterTypeProvider(methodParameter), owner.asVariableResolver()).
getNested(methodParameter.getNestingLevel(), methodParameter.typeIndexesPerLevel);
}
/**
* Return a {@link ResolvableType} for the specified {@link MethodParameter},
* overriding the target type to resolve with a specific given type.
* @param methodParameter the source method parameter (must not be {@code null})
* @param targetType the type to resolve (a part of the method parameter's type)
* @return a {@link ResolvableType} for the specified method parameter
* @see #forMethodParameter(Method, int)
*/
public static ResolvableType forMethodParameter(MethodParameter methodParameter, @Nullable Type targetType) {
Assert.notNull(methodParameter, "MethodParameter must not be null");
return forMethodParameter(methodParameter, targetType, methodParameter.getNestingLevel());
}
/**
* Return a {@link ResolvableType} for the specified {@link MethodParameter} at
* a specific nesting level, overriding the target type to resolve with a specific
* given type.
* @param methodParameter the source method parameter (must not be {@code null})
* @param targetType the type to resolve (a part of the method parameter's type)
* @param nestingLevel the nesting level to use
* @return a {@link ResolvableType} for the specified method parameter
* @since 5.2
* @see #forMethodParameter(Method, int)
*/
static ResolvableType forMethodParameter(
MethodParameter methodParameter, @Nullable Type targetType, int nestingLevel) {
ResolvableType owner = forType(methodParameter.getContainingClass()).as(methodParameter.getDeclaringClass());
return forType(targetType, new MethodParameterTypeProvider(methodParameter), owner.asVariableResolver()).
getNested(nestingLevel, methodParameter.typeIndexesPerLevel);
}
和forField()的參數(shù)字段類型大體相同,只是多了下標(biāo)和目標(biāo)類型的支持而已。
forType
除了ResolvableType的構(gòu)造方法,上面的所有方法,最終都調(diào)用了forType方法。因此,這個方法非常關(guān)鍵。
/**
* Return a {@link ResolvableType} for the specified {@link Type} backed by a given
* {@link VariableResolver}.
* @param type the source type or {@code null}
* @param typeProvider the type provider or {@code null}
* @param variableResolver the variable resolver or {@code null}
* @return a {@link ResolvableType} for the specified {@link Type} and {@link VariableResolver}
*/
static ResolvableType forType(
@Nullable Type type, @Nullable TypeProvider typeProvider, @Nullable VariableResolver variableResolver) {
// 當(dāng)類型為null且類型提供者不為空時,重新生成type。
// 這是為什么呢?其實(shí)是為了更好地支持序列化操作。
if (type == null && typeProvider != null) {
type = SerializableTypeWrapper.forTypeProvider(typeProvider);
}
// 類型為空時,直接映射為空對象返回
if (type == null) {
return NONE;
}
// 簡單的Class類型,也可以直接構(gòu)造出來
// For simple Class references, build the wrapper right away -
// no expensive resolution necessary, so not worth caching...
if (type instanceof Class) {
return new ResolvableType(type, typeProvider, variableResolver, (ResolvableType) null);
}
// Purge empty entries on access since we don't have a clean-up thread or the like.
cache.purgeUnreferencedEntries();
// Check the cache - we may have a ResolvableType which has been resolved before...
// 這兒先嘗試用緩存獲取,如果沒獲取到,則構(gòu)造一次,存儲到緩存,并返回resolved字段。
// resolved字段在哪生成的呢?其實(shí)是在ResolvableType構(gòu)造方法。
// ResolvableType構(gòu)造方法又調(diào)用了resolveClass方法。
ResolvableType resultType = new ResolvableType(type, typeProvider, variableResolver);
ResolvableType cachedType = cache.get(resultType);
if (cachedType == null) {
cachedType = new ResolvableType(type, typeProvider, variableResolver, resultType.hash);
cache.put(cachedType, cachedType);
}
resultType.resolved = cachedType.resolved;
return resultType;
}
SerializableTypeWrapper.forTypeProvider
在forType()中有一個關(guān)鍵的地方,在于SerializableTypeWrapper.forTypeProvider的調(diào)用,它主要提供了序列化功能的支持。
private static final Class<?>[] SUPPORTED_SERIALIZABLE_TYPES = {
GenericArrayType.class, ParameterizedType.class, TypeVariable.class, WildcardType.class};
static Type forTypeProvider(TypeProvider provider) {
Type providedType = provider.getType();
if (providedType == null || providedType instanceof Serializable) {
// No serializable type wrapping necessary (e.g. for java.lang.Class)
return providedType;
}
if (GraalDetector.inImageCode() || !Serializable.class.isAssignableFrom(Class.class)) {
// Let's skip any wrapping attempts if types are generally not serializable in
// the current runtime environment (even java.lang.Class itself, e.g. on Graal)
return providedType;
}
// Obtain a serializable type proxy for the given provider...
Type cached = cache.get(providedType);
if (cached != null) {
return cached;
}
for (Class<?> type : SUPPORTED_SERIALIZABLE_TYPES) {
if (type.isInstance(providedType)) {
ClassLoader classLoader = provider.getClass().getClassLoader();
Class<?>[] interfaces = new Class<?>[] {type, SerializableTypeProxy.class, Serializable.class};
InvocationHandler handler = new TypeProxyInvocationHandler(provider);
cached = (Type) Proxy.newProxyInstance(classLoader, interfaces, handler);
cache.put(providedType, cached);
return cached;
}
}
throw new IllegalArgumentException("Unsupported Type class: " + providedType.getClass().getName());
}
其主要對非Class的類型,通過JDK動態(tài)代理的方式,對序列化功能(通過實(shí)現(xiàn)Serializable接口)進(jìn)行了增強(qiáng)。除此之外,還增加了對equals、hashCode、getTypeProvider等的增強(qiáng)實(shí)現(xiàn)。
private static class TypeProxyInvocationHandler implements InvocationHandler, Serializable {
private final TypeProvider provider;
public TypeProxyInvocationHandler(TypeProvider provider) {
this.provider = provider;
}
@Override
@Nullable
public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
// equals動態(tài)代理
if (method.getName().equals("equals") && args != null) {
Object other = args[0];
// Unwrap proxies for speed
// 解包的目的是為了提高性能
if (other instanceof Type) {
other = unwrap((Type) other);
}
return ObjectUtils.nullSafeEquals(this.provider.getType(), other);
}
// hashCode動態(tài)代理
else if (method.getName().equals("hashCode")) {
return ObjectUtils.nullSafeHashCode(this.provider.getType());
}
// getTypeProvider動態(tài)代理
else if (method.getName().equals("getTypeProvider")) {
return this.provider;
}
// 返回類型為Type的動態(tài)代理,最終調(diào)用的是provider的實(shí)現(xiàn)
if (Type.class == method.getReturnType() && args == null) {
return forTypeProvider(new MethodInvokeTypeProvider(this.provider, method, -1));
}
// 返回類型為Type數(shù)組的動態(tài)代理,最終調(diào)用的是provider的實(shí)現(xiàn)
else if (Type[].class == method.getReturnType() && args == null) {
Type[] result = new Type[((Type[]) method.invoke(this.provider.getType())).length];
for (int i = 0; i < result.length; i++) {
result[i] = forTypeProvider(new MethodInvokeTypeProvider(this.provider, method, i));
}
return result;
}
try {
return method.invoke(this.provider.getType(), args);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
resolveClass
@Nullable
private Class<?> resolveClass() {
// 空類型直接返回
if (this.type == EmptyType.INSTANCE) {
return null;
}
// Class對象,也直接返回
if (this.type instanceof Class) {
return (Class<?>) this.type;
}
// 泛型數(shù)組類型,通過getComponentType()來轉(zhuǎn)換生成
if (this.type instanceof GenericArrayType) {
Class<?> resolvedComponent = getComponentType().resolve();
return (resolvedComponent != null ? Array.newInstance(resolvedComponent, 0).getClass() : null);
}
// 底層調(diào)用了resolveType()
return resolveType().resolve();
}
resolveType
/**
* Resolve this type by a single level, returning the resolved value or {@link #NONE}.
* <p>Note: The returned {@link ResolvableType} should only be used as an intermediary
* as it cannot be serialized.
*/
ResolvableType resolveType() {
// 參數(shù)化類型,通過`getRawType()`獲取原始類型
if (this.type instanceof ParameterizedType) {
return forType(((ParameterizedType) this.type).getRawType(), this.variableResolver);
}
// 通配符類型,通過上界和下屆獲取類型
if (this.type instanceof WildcardType) {
Type resolved = resolveBounds(((WildcardType) this.type).getUpperBounds());
if (resolved == null) {
resolved = resolveBounds(((WildcardType) this.type).getLowerBounds());
}
return forType(resolved, this.variableResolver);
}
// 類型變量類型,當(dāng)類型變量處理器不為空,則直接由其處理;否則通過其上界來獲取
if (this.type instanceof TypeVariable) {
TypeVariable<?> variable = (TypeVariable<?>) this.type;
// Try default variable resolution
if (this.variableResolver != null) {
ResolvableType resolved = this.variableResolver.resolveVariable(variable);
if (resolved != null) {
return resolved;
}
}
// Fallback to bounds
return forType(resolveBounds(variable.getBounds()), this.variableResolver);
}
return NONE;
}
這個方法對參數(shù)化類型、通配符類型、類型變量進(jìn)行了適配和轉(zhuǎn)換。最終又調(diào)回了forType()方法。這樣就出現(xiàn)了循環(huán)調(diào)用的情況,感覺會出問題,如下所示:
forType() -> ResolvableType() -> resolveClass() -> resolveType() -> forType() -> ...
其實(shí),這樣調(diào)用是有原因的。原因在于,參數(shù)化類型、通配符類型、類型變量,都是可以相互嵌套的。例如:List<? extends List<String>>,就是通配符嵌套參數(shù)化類型。
其他方法
其他的方法含義,可以參考官方提供的測試類,ResolvableTypeTests。其覆蓋場景非常廣泛,簡簡單單的一個測試類,代碼行數(shù)就達(dá)到了1300+行,簡直令人發(fā)指!
總結(jié)
本文翻譯了部分Spring官方提供的javadoc,同時對內(nèi)部的核心實(shí)現(xiàn)方法進(jìn)行了詳細(xì)而全面的分析,基本上了解了Spring是如何對java Type進(jìn)行封裝的。當(dāng)然,分析源碼的過程中,我們看到其實(shí)現(xiàn)非常精彩。
但是,對于一些細(xì)節(jié),樓主并沒有深入分析。樓主覺得,如果進(jìn)行全面的分析,浪費(fèi)篇章的同時,也可能出現(xiàn)闡釋不清楚的情況。