在本篇中,我们暂且不还之前的债
- Configuration
- TypeAliasRegistry
- TypeHandlerRegistry
而是对之前反射包下的类做补充说明。
回顾一下,之前我们介绍了MyBatis框架下的refection包:
MyBatis下的refection包
在其中我们介绍了DefaultObjectFactory、DefaultReflectorFactory、Reflector。大家对其他的类可能有充满了好奇,所以本章是作为补充。
可能会问这个和主流程相关么?看这个源码有什么好处么?
回答是和主流程不相关,但是主流程中大量用了这些辅助类用来简化操作,如果不看懂,那主流程源码会是雾里看花,所谓磨刀不误砍柴工,所以今天我就来介绍几个在主流程源码上经常使用的类。
1.TypeParameterResolver源码解析
这里我们还是借助于官方源码提供的测试类TypeParameterResolverTest,一个好的类名可以让我们不看起内部而知道其意,看这个方法,我们猜测应该是和参数类型解析有关,那么我们先来看一个测试类中的测试方法:
// TypeParameterResolverTest
@Test
void testReturn_Lv0SimpleClass() throws Exception {
Class<?> clazz = Level0Mapper.class;
Method method = clazz.getMethod("simpleSelect");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertEquals(Double.class, result);
}
```java
public interface Level0Mapper<L, M, N> {
Double simpleSelect();
。。。
interface Level0InnerMapper extends Level0Mapper<String, Long, Float> {
}
}
感觉这样子是不是和我们平常使用MyBatis有点联系了?都是接口。 我们继续往下看,因为TypeParameterResolver是辅助方法,内部都是静态方法,所以我们不分析起属性和构造函数,直接杀入调用方法:
//TypeParameterResolver
/**
* @return The return type of the method as {@link Type}. If it has type parameters in the declaration,<br>
* they will be resolved to the actual runtime {@link Type}s.
*/
public static Type resolveReturnType(Method method, Type srcType) {
Type returnType = method.getGenericReturnType();
Class<?> declaringClass = method.getDeclaringClass();
return resolveType(returnType, srcType, declaringClass);
}
/**
* 解析类型
*/
private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
if (type instanceof TypeVariable) {
return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
} else if (type instanceof ParameterizedType) {
return resolveParameterizedType((ParameterizedType) type, srcType, declaringClass);
} else if (type instanceof GenericArrayType) {
return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
} else {
return type;
}
}
这里按照这个规则,看到上述是Double,在判断type类型时,我们直接到了最下面一层,也就是直接返回。
我们来看继续下一个测试案例,首先是我们的Level0Mapper类方法:
//Level0Mapper
List<Double> simpleSelectList();
之后再来看继承关系Level1Mapper继承Level0Mapper方法:
public interface Level1Mapper<E, F> extends Level0Mapper<E, F, String> {
}
最后来看我们的测试案例:
@Test
void testReturn_SimpleList() throws Exception {
Class<?> clazz = Level1Mapper.class;
Method method = clazz.getMethod("simpleSelectList");
Type result = TypeParameterResolver.resolveReturnType(method, clazz);
assertTrue(result instanceof ParameterizedType);
ParameterizedType paramType = (ParameterizedType) result;
assertEquals(List.class, paramType.getRawType());
assertEquals(1, paramType.getActualTypeArguments().length);
assertEquals(Double.class, paramType.getActualTypeArguments()[0]);
}
这里可能会对ParameterizedType有疑问,认为这是什么类?充满了疑惑,这里简单介绍下:
ParameterizedType是Java解析泛型反射的类,我们看到上述接口返回应该是LIst<Double>,而Double是泛型。我们直接来看下上面那个方法对于泛型的处理,可能会有帮助理解:
private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type srcType, Class<?> declaringClass) {
Class<?> rawType = (Class<?>) parameterizedType.getRawType();
Type[] typeArgs = parameterizedType.getActualTypeArguments();
Type[] args = new Type[typeArgs.length];
for (int i = 0; i < typeArgs.length; i++) {
if (typeArgs[i] instanceof TypeVariable) {
args[i] = resolveTypeVar((TypeVariable<?>) typeArgs[i], srcType, declaringClass);
} else if (typeArgs[i] instanceof ParameterizedType) {
args[i] = resolveParameterizedType((ParameterizedType) typeArgs[i], srcType, declaringClass);
} else if (typeArgs[i] instanceof WildcardType) {
args[i] = resolveWildcardType((WildcardType) typeArgs[i], srcType, declaringClass);
} else {
args[i] = typeArgs[i];
}
}
return new ParameterizedTypeImpl(rawType, null, args);
}
我们可以看下这个内部类ParameterizedTypeImpl
static class ParameterizedTypeImpl implements ParameterizedType {
private Class<?> rawType;
private Type ownerType;
private Type[] actualTypeArguments;
public ParameterizedTypeImpl(Class<?> rawType, Type ownerType, Type[] actualTypeArguments) {
super();
this.rawType = rawType;
this.ownerType = ownerType;
this.actualTypeArguments = actualTypeArguments;
}
@Override
public Type[] getActualTypeArguments() {
return actualTypeArguments;
}
@Override
public Type getOwnerType() {
return ownerType;
}
@Override
public Type getRawType() {
return rawType;
}
@Override
public String toString() {
return "ParameterizedTypeImpl [rawType=" + rawType + ", ownerType=" + ownerType + ", actualTypeArguments=" + Arrays.toString(actualTypeArguments) + "]";
}
}
我们只需要熟悉ParameterizedType,方法逻辑不难理解。List可类比Map类型,这里不做展开。这里我们就分析这两种,其实只需知道这个方法类是用来解析返回类型即可。具体细节可有需要在深入。
2.MetaClass源码解析
下面我们来分析refection包下的MetaClass类,那么这个类是干什么的呢?见名知意起应该是存储类元信息的,我们来揭开它的面纱。我们继续从test方法入手,先从MetaClassTest中的第一个Test方法开始撸:
@Test
void shouldTestDataTypeOfGenericMethod() {
ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
MetaClass meta = MetaClass.forClass(GenericConcrete.class, reflectorFactory);
assertEquals(Long.class, meta.getGetterType("id"));
assertEquals(Long.class, meta.getSetterType("id"));
}
那么我们跟随进入MetaClass.forClass方法:
public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) {
return new MetaClass(type, reflectorFactory);
}
/**
* 我们可以看出这里就是ReflectorFactory和创建Reflector
*/
private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
this.reflectorFactory = reflectorFactory;
this.reflector = reflectorFactory.findForClass(type);
}
我这边也来总结一下,有利于让你更好的理解:
MetaClass是对Reflector的封装,使用装饰者模式。
具体我们可以来看下meta的getGetterType方法:
public Class<?> getGetterType(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaClass metaProp = metaClassForProperty(prop);
return metaProp.getGetterType(prop.getChildren());
}
// issue #506. Resolve the type inside a Collection Object
return getGetterType(prop);
}
/**
* 获取属性对应类型,并进行构建MetaClass返回
*/
private MetaClass metaClassForProperty(PropertyTokenizer prop) {
Class<?> propType = getGetterType(prop);
return MetaClass.forClass(propType, reflectorFactory);
}
/**
* 从reflector中获取对应name的类类型
*/
private Class<?> getGetterType(PropertyTokenizer prop) {
Class<?> type = reflector.getGetterType(prop.getName());
if (prop.getIndex() != null && Collection.class.isAssignableFrom(type)) {
Type returnType = getGenericGetterType(prop.getName());
if (returnType instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments();
if (actualTypeArguments != null && actualTypeArguments.length == 1) {
returnType = actualTypeArguments[0];
if (returnType instanceof Class) {
type = (Class<?>) returnType;
} else if (returnType instanceof ParameterizedType) {
type = (Class<?>) ((ParameterizedType) returnType).getRawType();
}
}
}
}
return type;
}
这里的逻辑暂且不谈,我们先来看这里又引入的PropertyTokenizer类。
2.1 PropertyTokenizer类方法解析
我们继续来看他的属性和构造方法:
public class PropertyTokenizer implements Iterator<PropertyTokenizer> {
private String name;
private final String indexedName;
private String index;
private final String children;
/**
* 这里的作用是解析层级关系
* 例: fullname=richType.richList[0]
* 则第一层name = richType, children = richList[0],别的为null
* 第二层name = richList, indexedName = richList[0], index = 0
*/
public PropertyTokenizer(String fullname) {
int delim = fullname.indexOf('.');
if (delim > -1) {
name = fullname.substring(0, delim);
children = fullname.substring(delim + 1);
} else {
name = fullname;
children = null;
}
indexedName = name;
delim = name.indexOf('[');
if (delim > -1) {
index = name.substring(delim + 1, name.length() - 1);
name = name.substring(0, delim);
}
}
public String getName() {
return name;
}
public String getIndex() {
return index;
}
public String getIndexedName() {
return indexedName;
}
public String getChildren() {
return children;
}
@Override
public boolean hasNext() {
return children != null;
}
@Override
public PropertyTokenizer next() {
return new PropertyTokenizer(children);
}
@Override
public void remove() {
throw new UnsupportedOperationException("Remove is not supported, as it has no meaning in the context of properties.");
}
}
在上面的注释中,我把逻辑写的比较详细了,就是递归解析参数。这里我们可以了解到我们之前使用richType.richList[0]这里能解析进去都是靠这个辅助类的帮助。
2.2 MetaClass的getGetterType方法分析
/**
* 从reflector中获取对应name的类类型
*/
private Class<?> getGetterType(PropertyTokenizer prop) {
//这里的prop会递归调用到最后一层,这一步可以拿到prop的get方法
Class<?> type = reflector.getGetterType(prop.getName());
if (prop.getIndex() != null && Collection.class.isAssignableFrom(type)) {
Type returnType = getGenericGetterType(prop.getName());
if (returnType instanceof ParameterizedType) {
Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments();
if (actualTypeArguments != null && actualTypeArguments.length == 1) {
returnType = actualTypeArguments[0];
if (returnType instanceof Class) {
type = (Class<?>) returnType;
} else if (returnType instanceof ParameterizedType) {
type = (Class<?>) ((ParameterizedType) returnType).getRawType();
}
}
}
}
return type;
}
/**
* 解析列表类型
*/
private Type getGenericGetterType(String propertyName) {
try {
//获取属性的Get方法执行器
Invoker invoker = reflector.getGetInvoker(propertyName);
// 通过invoker获取对应属性,这里MethodInvoker、GetFieldInvoker的作用就是取属性
// 无非一个是通过Get方法调用获取,一个是直接属性反射获取
if (invoker instanceof MethodInvoker) {
Field _method = MethodInvoker.class.getDeclaredField("method");
_method.setAccessible(true);
Method method = (Method) _method.get(invoker);
return TypeParameterResolver.resolveReturnType(method, reflector.getType());
} else if (invoker instanceof GetFieldInvoker) {
Field _field = GetFieldInvoker.class.getDeclaredField("field");
_field.setAccessible(true);
Field field = (Field) _field.get(invoker);
return TypeParameterResolver.resolveFieldType(field, reflector.getType());
}
} catch (NoSuchFieldException | IllegalAccessException ignored) {
}
return null;
}
帮大家梳理一下逻辑。meta.getGetterType方法是把传参的数据先解析出来,比如入参为嵌套的那种模式name=richType.richList[0],这个使用我们先通过PropertyTokenizer把是在richType类下的richList解析出来,然后通过reflector加载richType类,得到对应属性获取值大的方法MethodInvoker或者GetFieldInvoker,然后调用获取到属性值。
如果大家还是对这块有点疑问,可以直接调试下代码,会更加有助于理解。因为这块涉及到递归调用,口述方式我可能讲的会不太明白。
3. 今日总结
今天我们讲了关于TypeParameterResolver静态辅助类,MetaClass类元信息获取类的源码,希望大家能有收货~~
网友评论