前两篇博客中很多地方都是用到了ResolvableType获取类型信息,这篇就来详细看看它。
ResolvableType封装了Java的Type,提供了getSuperType()方法访问父类型,getInterfaces()反回实现的接口,getGeneric()获取泛型参数,resolve()转化为Class对象。那么什么事Java的Type呢,可以看出Type有四个子接口,一个子类。每种类型代表啥意思可以参考这篇文章《Java Type详解》。下面看看ResolvableType具体实现。
ResolvableType的构造函数都是私有的,提供了四类实例化对象的静态方法:
每个方法最终都会调用同一个构造方法
static ResolvableType forType(
@Nullable Type type, @Nullable TypeProvider typeProvider, @Nullable VariableResolver variableResolver);
先来看看forField()方法:
public static ResolvableType forField(Field field) {
Assert.notNull(field, "Field must not be null");
return forType(null, new FieldTypeProvider(field), null);
}
首先将field封装成FieldTypeProvider,然后调用上述都会使用的forType()方法。FieldTypeProvider实现了TypeProvider接口,该接口有两个方法,对于FieldTypeProvider就是返回字段的类型Class对象和该字段本身的Field对象。
interface TypeProvider extends Serializable {
@Nullable
Type getType();
@Nullable
default Object getSource() {
return null;
}
}
static class FieldTypeProvider implements TypeProvider {
private final String fieldName;
private final Class> declaringClass;
private transient Field field;
public FieldTypeProvider(Field field) {
this.fieldName = field.getName();
this.declaringClass = field.getDeclaringClass();
this.field = field;
}
@Override
public Type getType() {
return this.field.getGenericType();
}
@Override
public Object getSource() {
return this.field;
}
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
inputStream.defaultReadObject();
try {
this.field = this.declaringClass.getDeclaredField(this.fieldName);
}
catch (Throwable ex) {
throw new IllegalStateException("Could not find original class structure", ex);
}
}
}
下面看一下都会用到的forType()方法。
static ResolvableType forType(
@Nullable Type type, @Nullable TypeProvider typeProvider, @Nullable VariableResolver variableResolver) {
if (type == null && typeProvider != null) {
type = SerializableTypeWrapper.forTypeProvider(typeProvider);
}
if (type == null) {
return NONE;
}
// 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...
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;
}
上面代码获取type时没有简单的调用typeProvider.getType(),而是使用SerializableTypeWrapper.forTypeProvider(typeProvider)包装了一个代理类,这么做的目的是为了type可以序列化,因为代理类实现了Serializable接口。
static Type forTypeProvider(final TypeProvider provider) {
Assert.notNull(provider, "Provider must not be null");
Type providedType = provider.getType();
if (providedType == null) {
return null;
}
if (providedType instanceof Serializable) {
return providedType;
}
Type cached = cache.get(providedType);
if (cached != null) {
return cached;
}
for (Class> type : SUPPORTED_SERIALIZABLE_TYPES) {
if (type.isAssignableFrom(providedType.getClass())) {
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());
}
TypeProxyInvocationHandler。
public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
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);
}
else if (method.getName().equals("hashCode")) {
return ObjectUtils.nullSafeHashCode(this.provider.getType());
}
else if (method.getName().equals("getTypeProvider")) {
return this.provider;
}
if (Type.class == method.getReturnType() && args == null) {
return forTypeProvider(new MethodInvokeTypeProvider(this.provider, method, -1));
}
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();
}
}
在结合ResolvableType的getType()方法看一下,如果type是代理对象则先调用getTypeProvider()方法得到TypeProvider在调用getType()方法获取到Type。
public Type getType() {
return SerializableTypeWrapper.unwrap(this.type);
}
public static T unwrap(T type) {
Type unwrapped = type;
while (unwrapped instanceof SerializableTypeProxy) {
unwrapped = ((SerializableTypeProxy) type).getTypeProvider().getType();
}
return (unwrapped != null ? (T) unwrapped : type);
}
获取type先通过构造函数实例化一个resultType,这个resultType的resolved暂时是null。间接的通过使用相同的Type和TypeProvider作为参数使用另一构造函数实例化一个临时的对象,因为这个构造函数可以生成resolved,再将resolved赋值给 resultType。那为啥不直接使用后者实例化对象呢,因为后者需要一个hashcode,而前者可以生成hashcode。
生成hashCode。
private int calculateHashCode() {
int hashCode = ObjectUtils.nullSafeHashCode(this.type);
if (this.typeProvider != null) {
hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.typeProvider.getType());
}
if (this.variableResolver != null) {
hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.variableResolver.getSource());
}
if (this.componentType != null) {
hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.componentType);
}
return hashCode;
}
生成resolved。
private Class> resolveClass() {
if (this.type == EmptyType.INSTANCE) {
return null;
}
if (this.type instanceof Class) {
return (Class>) this.type;
}
if (this.type instanceof GenericArrayType) {
Class> resolvedComponent = getComponentType().resolve();
return (resolvedComponent != null ? Array.newInstance(resolvedComponent, 0).getClass() : null);
}
return resolveType().resolve();
}
ResolvableType resolveType() {
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);
}
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;
}
resolveClass()方法的目的就是将type转换成相关的Class对象,因为只有满足type instanceof Class才返回,否则继续调用forType()递归上面的代码。
ResolvableType还有一个as方法,功能是沿着继承链向上查找参数指定的ResolvableType。
public ResolvableType as(Class> type) {
if (this == NONE) {
return NONE;
}
if (ObjectUtils.nullSafeEquals(resolve(), type)) {
return this;
}
for (ResolvableType interfaceType : getInterfaces()) {
ResolvableType interfaceAsType = interfaceType.as(type);
if (interfaceAsType != NONE) {
return interfaceAsType;
}
}
return getSuperType().as(type);
}
下面看看文章开头提及的getSuperType()方法。
public ResolvableType getSuperType() {
Class> resolved = resolve();
if (resolved == null || resolved.getGenericSuperclass() == null) {
return NONE;
}
ResolvableType superType = this.superType;
if (superType == null) {
superType = forType(SerializableTypeWrapper.forGenericSuperclass(resolved), asVariableResolver());
this.superType = superType;
}
return superType;
}
SerializableTypeWrapper.forGenericSuperclass(resolved)方法返回当前Class对象父类的可序列化的Type对象,asVariableResolver返回一个DefaultVariableResolver对象,它的resolveVariable()方法用于将TypeVariable转化成 ResolvableType对象,这个类会在isAssignableFrom()方法用到。
private class DefaultVariableResolver implements VariableResolver { @Override @Nullable public ResolvableType resolveVariable(TypeVariable> variable) { return ResolvableType.this.resolveVariable(variable); } @Override public Object getSource() { return ResolvableType.this; } }