Spring 系列目錄(http://www.javashuo.com/article/p-kqecupyl-bm.html)html
Java Type 泛型系列文章:java
Spring 中大量使用反射,須要獲取泛型的具體類型,爲此專門提供了一個工具類解析泛型 - ResolvalbeType。ResolvableType 是對 Class,Field,Method 獲取 Type 的抽象。spring
interface Service<N, M> { } class ServiceImpl<A, B> implements Service<String, Integer> { public ServiceImpl(List<List<String>> list, Map<Double, Map<Float, Integer>> map) { } }
(1) forClass數組
@Test public void forClassTest() { ResolvableType resolvableType = ResolvableType.forClass(ServiceImpl.class); // getType 保存原始的 Type 類型 Assert.assertEquals(ServiceImpl.class, resolvableType.getType()); // resolve 將 Type 解析爲 Class, 若是沒法解析返回 null Assert.assertEquals(ServiceImpl.class, resolvableType.resolve()); }
(2) forField緩存
private Service<Double, Float> service; private List<List<String>> list; private Map<String, Map<String, Integer>> map; private List<String>[] array; @Test public void forFieldTest() { // 1. Service<Double, Float> service Field filed = ReflectionUtils.findField(ResolveTypeTest.class, "service"); ResolvableType resolvableType = ResolvableType.forField(filed); // getType() 保存原始的 Type 類型 Assert.assertEquals(filed.getGenericType(), resolvableType.getType()); // resolve() 對於 ParameterizedType 類型保存的是 <> 以前的類型,即 Service.class Assert.assertEquals(((ParameterizedType) filed.getGenericType()).getRawType(), resolvableType.resolve()); Class<?> clazz = resolvableType.getGeneric(0).resolve(); Assert.assertEquals(Double.class, clazz); // 2. List<List<String>> list resolvableType = ResolvableType.forField( ReflectionUtils.findField(ResolveTypeTest.class, "list")); // 下面兩種獲取泛型的方式等價 clazz = resolvableType.getGeneric(0).getGeneric(0).resolve(); Assert.assertEquals(String.class, clazz); clazz = resolvableType.getGeneric(0, 0).resolve(); Assert.assertEquals(String.class, clazz); // 3. Map<String, Map<String, Integer>> map resolvableType = ResolvableType.forField( ReflectionUtils.findField(ResolveTypeTest.class, "map")); clazz = resolvableType.getGeneric(1).getGeneric(1).resolve(); Assert.assertEquals(Integer.class, clazz); // 4. List<String>[] array resolvableType = ResolvableType.forField( ReflectionUtils.findField(ResolveTypeTest.class, "array")); Assert.assertTrue(resolvableType.isArray()); Assert.assertEquals(List.class, resolvableType.getComponentType().resolve()); Assert.assertEquals(String.class, resolvableType.getComponentType().getGeneric(0).resolve()); }
(3) forMethodParameterapp
forMethodParameter 還有不少變種:如 forConstructorParameter、forMethodReturnTypeide
@Test public void forMethodTest() { // 1. 方法的返回值類型 ResolvableType returnType = ResolvableType.forMethodReturnType( ReflectionUtils.findMethod(ServiceImpl.class, "method")); Assert.assertEquals(Double.class, returnType.getGeneric(1, 0).resolve()); // 2. 構造器 ServiceImpl(List<List<String>> list, Map<Double, Map<Float, Integer>> map) ResolvableType parameterType = ResolvableType.forConstructorParameter( ClassUtils.getConstructorIfAvailable(ServiceImpl.class, List.class, Map.class), 0); // List<List<String>> 的泛型第一層爲 <List<String>>,第二層爲 <String> Assert.assertEquals(String.class, parameterType.getGeneric(0, 0).resolve()); parameterType = ResolvableType.forConstructorParameter( ClassUtils.getConstructorIfAvailable(ServiceImpl.class, List.class, Map.class), 1); Assert.assertEquals(Double.class, parameterType.getGeneric(0).resolve()); Assert.assertEquals(Float.class, parameterType.getGeneric(1, 0).resolve()); Assert.assertEquals(Integer.class, parameterType.getGeneric(1, 1).resolve()); }
(4) 其它經常使用方法工具
@Test public void test() { // HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable ResolvableType resolvableType = ResolvableType.forClass(HashMap.class); // 1. getInterfaces 獲取接口 Assert.assertEquals(Map.class, resolvableType.getInterfaces()[0].resolve()); // 2. getSuperType 獲取父類 Assert.assertEquals(AbstractMap.class, resolvableType.getSuperType().resolve()); // 3. as 向上轉型 Map<K,V> ResolvableType mapResolvableType = resolvableType.as(Map.class); Assert.assertEquals(Map.class, mapResolvableType.resolve()); // 4. getRawClass 當 type 是 ParameterizedType 時有效 Assert.assertEquals(Map.class, mapResolvableType.getRawClass()); Assert.assertEquals(HashMap.class.getGenericInterfaces()[0], mapResolvableType.getType()); // 5. getGeneric 獲取泛型 class ServiceImpl<A, B> implements Service<String, Integer> resolvableType = ResolvableType.forClass(ServiceImpl.class); // 當 Type 沒法找到具體的 class 類型時返回 null Assert.assertEquals("A", resolvableType.getGeneric(0).getType().getTypeName()); Assert.assertEquals(null, resolvableType.getGeneric(0).resolve()); // 如下兩種獲取泛型的 Class 類型方式等價 Assert.assertEquals(String.class, resolvableType.as(Service.class).getGeneric(0).resolve()); Assert.assertEquals(String.class, resolvableType.as(Service.class).resolveGeneric(0)); // 5. getComponentType 獲取數組泛型 List<String>[] array resolvableType = ResolvableType.forField( ReflectionUtils.findField(ResolveTypeTest.class, "array")); Assert.assertEquals(List.class, resolvableType.getComponentType().resolve()); }
(5) 建立 ResolvableType源碼分析
@Test public void test() { ResolvableType resolvableType1 = ResolvableType.forClassWithGenerics(List.class, String.class); ResolvableType resolvableType2 = ResolvableType.forArrayComponent(resolvableType1); resolvableType2.getComponentType().getGeneric(0).resolve(); // List<String>[] array ResolvableType resolvableType3 = ResolvableType.forField( ReflectionUtils.findField(ResolveTypeTest.class, "array")); Assert.assertTrue(resolvableType3.isAssignableFrom(resolvableType2)); Assert.assertTrue(ResolvableType.forClass(Object.class).isAssignableFrom( ResolvableType.forClass(String.class))); }
經過使用也能夠看出 ResolvableType 最主要的目的是解析傳入的 Type 類型,並經過 resolve() 獲取真實的 Class 類型。this
(1) ResolvalbeType 重要屬性
// 須要解析的 JDK Type 類型 private final Type type; // 緩存解析後的 Class 類型 private Class<?> resolved; // 緩存解析後父類、接口、泛型、數組泛型等 private volatile ResolvableType superType; private volatile ResolvableType[] interfaces; private volatile ResolvableType[] generics; private final ResolvableType componentType;
另外還有兩個工具類輔助解析用:
// 對 Type 進行封裝 private final TypeProvider typeProvider; // 對 TypeVariable 如何解析爲 Class 的策略 private final VariableResolver variableResolver;
(2) forField
下面以 forField(Field field) 爲例,看 ResolvalbeType 是如何解析泛型的。
public static ResolvableType forField(Field field) { Assert.notNull(field, "Field must not be null"); return forType(null, new FieldTypeProvider(field), null); } static ResolvableType forType(Type type, TypeProvider typeProvider, VariableResolver variableResolver) { if (type == null && typeProvider != null) { type = SerializableTypeWrapper.forTypeProvider(typeProvider); } if (type == null) { return NONE; } // 1. Class 不用解析,因此不必不緩存 if (type instanceof Class) { return new ResolvableType(type, typeProvider, variableResolver, (ResolvableType) null); } cache.purgeUnreferencedEntries(); // 2. 其他的 Type 類型須要解析,因此先緩存起來 // 2.1 這個構造器專爲緩存使用,不會觸發 resolveClass() 操做 ResolvableType resultType = new ResolvableType(type, typeProvider, variableResolver); ResolvableType cachedType = cache.get(resultType); if (cachedType == null) { // 2.2 若是緩存中沒有就須要解析了,這個構造器會觸發 resolveClass() 操做 cachedType = new ResolvableType(type, typeProvider, variableResolver, resultType.hash); cache.put(cachedType, cachedType); } resultType.resolved = cachedType.resolved; return resultType; }
解析 Type 對應的真實 Class 類型在 cachedType = new ResolvableType(type, typeProvider, variableResolver, resultType.hash)
這一步,會觸發 resolveClass() 操做。
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(); // 關鍵 }
(3) resolveClass
resolveClass() 方法先對兩種簡單的類型 Class 和 GenericArrayType 進行了解析,其他的 Type 類型則委託給了 resolveType() 方法解析。
private Class<?> resolveClass() { if (this.type == EmptyType.INSTANCE) { return null; } // 1. Class 類型 if (this.type instanceof Class) { return (Class<?>) this.type; } // 2. GenericArrayType 泛型數組,成員變量的 Class 類型 if (this.type instanceof GenericArrayType) { Class<?> resolvedComponent = getComponentType().resolve(); return (resolvedComponent != null ? Array.newInstance(resolvedComponent, 0).getClass() : null); } return resolveType().resolve(); }
對於 Class 和 GenericArrayType 兩種 Type 類型:
Class
解析後仍爲該 Class 類型GenericArrayType
該泛型數組成員變量的 Class 類型(4) resolveType
剩餘的 ParameterizedType、WildcardType、TypeVariable 三種類型繼續解析。
ResolvableType resolveType() { // 3. ParameterizedType 類型,getRawType 的 Class 類型 if (this.type instanceof ParameterizedType) { return forType(((ParameterizedType) this.type).getRawType(), this.variableResolver); } // 4. WildcardType 類型,上界或下界的 Class 類型,若有多個只取第一個 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); } // 5. TypeVariable 類型 if (this.type instanceof TypeVariable) { TypeVariable<?> variable = (TypeVariable<?>) this.type; // 5.1 使用 resolveVariable 解析 Try default variable resolution if (this.variableResolver != null) { ResolvableType resolved = this.variableResolver.resolveVariable(variable); if (resolved != null) { return resolved; } } // 5.2 TypeVariable 默認取上界的 Class 類型,若有多個只取第一個 return forType(resolveBounds(variable.getBounds()), this.variableResolver); } return NONE; }
resolveType對於 ParameterizedType、WildcardType、TypeVariable 三種 Type 類型:
ParameterizedType
getRawType 對應的 Class 類型WildcardType
上界或下界的 Class 類型,若有多個只取第一個TypeVariable
默認取上界的 Class 類型,若有多個只取第一個,也能夠是 variableResolver 解析,默認爲 DefaultVariableResolver(5) getGenerics
public ResolvableType[] getGenerics() { if (this == NONE) { return EMPTY_TYPES_ARRAY; } ResolvableType[] generics = this.generics; if (generics == null) { // 1. 獲取 Class 類型的泛型 if (this.type instanceof Class) { Type[] typeParams = ((Class<?>) this.type).getTypeParameters(); generics = new ResolvableType[typeParams.length]; for (int i = 0; i < generics.length; i++) { generics[i] = ResolvableType.forType(typeParams[i], this); } // 2. 獲取 ParameterizedType 類型的泛型 } else if (this.type instanceof ParameterizedType) { Type[] actualTypeArguments = ((ParameterizedType) this.type).getActualTypeArguments(); generics = new ResolvableType[actualTypeArguments.length]; for (int i = 0; i < actualTypeArguments.length; i++) { generics[i] = forType(actualTypeArguments[i], this.variableResolver); } // 3. WildcardType、TypeVariable 類型調用 resolveType() 從新解析 } else { generics = resolveType().getGenerics(); } this.generics = generics; } return generics; }
參考:
天天用心記錄一點點。內容也許不重要,但習慣很重要!