动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。反射的基本术语:Class、Constructor、Field、Method。
一、Reflector和ReflectorFactory
Reflector用于存储类的基本信息,是反射模块的基础,每个Reflector对象都对应一个类,Reflector中缓存反射需要的类的元信息。
//类的Class类型
private Class> type;
//可读属性,存在getter方法的属性
private String[] readablePropertyNames = EMPTY_STRING_ARRAY;
//可写属性,存在setter方法的属性
private String[] writeablePropertyNames = EMPTY_STRING_ARRAY;
//setter方法,key是属性名,value是Invoker,是对Method的封装
private Map setMethods = new HashMap();
//getter方法,key是属性名,value是Invoker,是对Method的封装
private Map getMethods = new HashMap();
//属性settter方法的参数值类型,key是属性名,value是参数类型
private Map> setTypes = new HashMap>();
//属性getter方法的参数值类型,key是属性名,value是返回值类型
private Map> getTypes = new HashMap>();
//无参构造
private Constructor> defaultConstructor;
//类中所有的属性,key是属性名的大写,value是属性名
private Map caseInsensitivePropertyMap = new HashMap();
在Reflector的构造方法中初始化上述的字段值。
public Reflector(Class> clazz) {
type = clazz;
addDefaultConstructor(clazz);
//处理clazz的getter方法,填充getMethods集合和getTypes集合
addGetMethods(clazz);
//处理clazz的setter方法,填充setMethods集合和setTypes集合
addSetMethods(clazz);
//处理没有getter/setter方法的字段
addFields(clazz);
//根据getMethods/setMethods方法,初始化可读/可写属性名称集合
readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]);
writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]);
//caseInsensitivePropertyMap中记录属性的大写名称
for (String propName : readablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
for (String propName : writeablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
}
举个例子,获取一个简单的JavaBean的Reflector信息。
//price没有对应的getter/setter方法
//存在getBuyTime/setBuyTime方法,但是未显示定义buyTime字段
class Car {
private String carNo;
private Integer price;
public String getCarNo() {
return carNo;
}
public void setCarNo(String carNo) {
this.carNo = carNo;
}
public String getBuyTime() {
return "2019-11-04";
}
public void setBuyTime(String time) {
}
}
ReflectorFactory是创建Reflector的接口,mybatis的唯一实现是DefaultReflectorFactory,可以完成对Reflector的创建和缓存。通过自定义ReflectorFactory实现类完成功能的扩展。
public class DefaultReflectorFactory implements ReflectorFactory {
//是否允许缓存类的Reflector对象
private boolean classCacheEnabled = true;
//使用map进行缓存,key是类的Class类型,vlaue是Reflector对象
private final ConcurrentMap, Reflector> reflectorMap = new ConcurrentHashMap, Reflector>();
public DefaultReflectorFactory() {
}
@Override
public boolean isClassCacheEnabled() {
return classCacheEnabled;
}
@Override
public void setClassCacheEnabled(boolean classCacheEnabled) {
this.classCacheEnabled = classCacheEnabled;
}
@Override
public Reflector findForClass(Class> type) {
if (classCacheEnabled) {
//允许使用缓存,先从缓存中查找,没有则新建Reflector对象,然后放入缓存中。
// synchronized (type) removed see issue #461
Reflector cached = reflectorMap.get(type);
if (cached == null) {
cached = new Reflector(type);
reflectorMap.put(type, cached);
}
return cached;
} else {
//不允许使用缓存,新建reflector对象
return new Reflector(type);
}
}
}
在获取一个类的getter方法时,会获取该类的所有方法再进行过滤,在获取所有方法的过程中会先获取该类的所有方法,为每个方法生成唯一的方法签名,同样会查询该类的所有接口的方法,该类的父类的所有方法。
private Method[] getClassMethods(Class> cls) {
Map uniqueMethods = new HashMap();
Class> currentClass = cls;
while (currentClass != null) {
//为每个公共方法生成唯一的方法签名,uniqueMethods的key就是方法的签名
//如:java.util.List#getNames
addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());
// we also need to look for interface methods -
// because the class may be abstract
//查找接口方法
Class>[] interfaces = currentClass.getInterfaces();
for (Class> anInterface : interfaces) {
addUniqueMethods(uniqueMethods, anInterface.getMethods());
}
//查找父类方法
currentClass = currentClass.getSuperclass();
}
Collection methods = uniqueMethods.values();
return methods.toArray(new Method[methods.size()]);
}
reflector.resovleGetterConflicts()方法,用于解决一个属性对应两个方法的问题。比如类SubA继承了A,A中有getNames方法,其返回值为List
二、TypeParameterResolver
当存在复杂的继承关系以及泛型定义时,TypeParameterResolver可以帮助我们解析字段,参数列表、返回值的类型,这是Reflector的基础。
TypeParameterResolver作为类型解析的工具类,所有方法的返回值都是Type类型,因此我们先从Type说起。Type是所有类型的公共接口,Class(实现类),ParameterizedType,GenericArrayType,TypeVariable、WildcardType。
ParameterizedType:泛型类型,如Map
getActualTypeArguments获取泛型类型,如String。
TypeVariable:类型变量,如List
WildcardType:通配符类型,如List extends Map>,List super List>。getUpperBounds获取上边界类型,getLowerBounds获取下边界类型。
GenericArrayType:泛型数组类型,元素类型需要是ParameterizedType或TypeVariable,如List
getGenericComponentType返回数值元素的类型,如List
Class:普通类型,除上述之外的类型。
类型存在嵌套。比如:
List
List
List
List extends Map>外层是ParameterizedType类型,里面是WildcardType类型。
介绍一种泛型特殊的使用场景:
public class MapperRegistry {
//泛型没有定义在类型,方法中使用到了泛型T(不管是参数列表还是返回值),因此需要在该方法上
//定义泛型,若方法中没有使用到泛型,可以不用写
@SuppressWarnings("unchecked")
public T getMapper(Class type, SqlSession sqlSession) {
final MapperProxyFactory mapperProxyFactory = (MapperProxyFactory) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
//Class>和Class的区别
//Class: T类型
//Class>: 通配类型,比如Class>[]则数组中的元素可以是任意类型的Class
//Class[]则数组中的元素可以是T类型的Class
public void addMappers(String packageName, Class> superType) {
ResolverUtil> resolverUtil = new ResolverUtil>();
resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
Set>> mapperSet = resolverUtil.getClasses();
for (Class> mapperClass : mapperSet) {
addMapper(mapperClass);
}
}
}
下面通过一个例子,解析如何在复杂的类继承关系和泛型定义中确认字段的类型,确定泛型的实际类型。
class ClassA {
protected Map map;
}
class SubClassA extends ClassA {
}
class TestType {
SubClassA sa = new SubClassA<>();
public static void main(String[] args) throws NoSuchFieldException {
//确定map中泛型的具体类型
Field f = ClassA.class.getDeclaredField("map");
Type type = TypeParameterResolver.resolveFieldType(f, TestType.class.getDeclaredField("sa").getGenericType());
System.out.println(type);
}
}
//打印结果:ParameterizedTypeImpl [rawType=interface java.util.Map, ownerType=null,actualTypeArguments=[class java.lang.Long, class java.lang.Long]]
//这是一个泛型类型,rawType是Map类型,k,v都是Long类型。
public static Type resolveFieldType(Field field, Type srcType) {
//获取map的声明类型,Map
Type fieldType = field.getGenericType();
//获取map所在类的Class类型,ClassA
Class> declaringClass = field.getDeclaringClass();
//srcType表示确定K,V类型查找的开始位置。
return resolveType(fieldType, srcType, declaringClass);
}
private static Type resolveType(Type type, Type srcType, Class> declaringClass) {
//根据type的类型选择合适的方法解析
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;
}
}
private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type srcType, Class> declaringClass) {
//获取Map的原始类型,Map
Class> rawType = (Class>) parameterizedType.getRawType();
//获取Map的实际类型,K/V
Type[] typeArgs = parameterizedType.getActualTypeArguments();
//args是实际确认的类型,此处是Long,Long
Type[] args = new Type[typeArgs.length];
for (int i = 0; i < typeArgs.length; i++) {
if (typeArgs[i] instanceof TypeVariable) {
//K,V是类型变量,走这个分支
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];
}
}
//返回ParameterizedTypeResolver的内部类,rawType:Map,args:Long,Long
return new ParameterizedTypeImpl(rawType, null, args);
}
private static Type resolveTypeVar(TypeVariable> typeVar, Type srcType, Class> declaringClass) {
Type result = null;
Class> clazz = null;
if (srcType instanceof Class) {
clazz = (Class>) srcType;
} else if (srcType instanceof ParameterizedType) {
//srcType的原始类型是SubClassA
ParameterizedType parameterizedType = (ParameterizedType) srcType;
clazz = (Class>) parameterizedType.getRawType();
} else {
throw new IllegalArgumentException("The 2nd arg must be Class or ParameterizedType, but was: " + srcType.getClass());
}
//相等表示需要解析的字段map是在SubClassA中,不使用上述示例
if (clazz == declaringClass) {
Type[] bounds = typeVar.getBounds();
if(bounds.length > 0) {
return bounds[0];
}
return Object.class;
}
//获取父类的声明类型,ClassA
Type superclass = clazz.getGenericSuperclass();
//递归整个继承结构,完成变量的解析工作
//类型对应:K,SubClassA,ClassA,SubClassA,ClassA
result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superclass);
if (result != null) {
return result;
}
//同上,扫描接口
Type[] superInterfaces = clazz.getGenericInterfaces();
for (Type superInterface : superInterfaces) {
result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superInterface);
if (result != null) {
return result;
}
}
return Object.class;
}
//见下图的解析流程
private static Type scanSuperTypes(TypeVariable> typeVar, Type srcType, Class> declaringClass, Class> clazz, Type superclass) {
Type result = null;
if (superclass instanceof ParameterizedType) {
ParameterizedType parentAsType = (ParameterizedType) superclass;
Class> parentAsClass = (Class>) parentAsType.getRawType();
if (declaringClass == parentAsClass) {
Type[] typeArgs = parentAsType.getActualTypeArguments();
TypeVariable>[] declaredTypeVars = declaringClass.getTypeParameters();
for (int i = 0; i < declaredTypeVars.length; i++) {
if (declaredTypeVars[i] == typeVar) {
if (typeArgs[i] instanceof TypeVariable) {
TypeVariable>[] typeParams = clazz.getTypeParameters();
for (int j = 0; j < typeParams.length; j++) {
if (typeParams[j] == typeArgs[i]) {
if (srcType instanceof ParameterizedType) {
result = ((ParameterizedType) srcType).getActualTypeArguments()[j];
}
break;
}
}
} else {
result = typeArgs[i];
}
}
}
} else if (declaringClass.isAssignableFrom(parentAsClass)) {
result = resolveTypeVar(typeVar, parentAsType, declaringClass);
}
} else if (superclass instanceof Class) {
if (declaringClass.isAssignableFrom((Class>) superclass)) {
result = resolveTypeVar(typeVar, superclass, declaringClass);
}
}
return result;
}
三、ObjectFactory
mybatis中很多地方都会用到ObjectFactory,通过对象工厂可创建指定类型的对象。DefaultObjectFactory是ObjectFactory的唯一实现。通过mybatis-config.xml中的配置可自定义ObjectFactory实现类。
四、Property工具集
PropertyTokenizer:解析mapper文件中的"."和"[]"符号。继承Iterator,可迭代处理。
//以orders[0].id为例,第一次调用PropertyTokenizer的构造方法时
//name:orders
//indexedName:orders[0]
//index:0
//children:id
public class PropertyTokenizer implements Iterator {
private String name;
private String indexedName;
private String index;
private String children;
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);
}
}
}
当需要解析的属性很复杂时,需要对PropertyTokenizer进行迭代处理。迭代的效果如下图。
public PropertyTokenizer next() {
return new PropertyTokenizer(children);
}
PropertyNamer:主要完成类中方法名到属性名的转换,具体实现主要是将方法中的set/get/is前缀去除。
PropertyCopier:属性拷贝工具类,主要完成相同类型的两个对象的属性拷贝。类似于BeanUtils、BeanCopier。
五、MetaClass
通过Reflector和PropertyTokenizer的组合,完成了对复杂属性表达式的解析。也可判断复杂属性是否有getter/setter方法。假设有一个用户对象User,订单对象Order,一个用户可以持有多个订单。
//reflectorFactory的缓存中取reflector信息
private ReflectorFactory reflectorFactory;
//类的元信息
private Reflector reflector;
private MetaClass(Class> type, ReflectorFactory reflectorFactory) {
this.reflectorFactory = reflectorFactory;
this.reflector = reflectorFactory.findForClass(type);
}
public static MetaClass forClass(Class> type, ReflectorFactory reflectorFactory) {
return new MetaClass(type, reflectorFactory);
}
MetaClass的主要方法有findProperty(name)、hasGetter(name)、hasSetter(name)方法,下面逐一讲解。
findProperty(name):完成复杂属性的验证工作(只查找 . 的导航的属性,不检查下标),如从User实体类中查找order.id属性是否存在,这里并不是直接验证User类中是否有order.id属性,而是先判断User中是否有order属性,再判断Order中是否有id属性。(注:User中持有Order对象)
//以order.id为例, 验证order.id是否有效,无效返回null,有效返回order.id
public String findProperty(String name) {
StringBuilder prop = buildProperty(name, new StringBuilder());
return prop.length() > 0 ? prop.toString() : null;
}
private StringBuilder buildProperty(String name, StringBuilder builder) {
//属性做分割,name:order,children:id
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
//从reflector中查找属性,为查到直接结束
String propertyName = reflector.findPropertyName(prop.getName());
if (propertyName != null) {
builder.append(propertyName);
builder.append(".");
//查到后获取order对应的类型,Order
MetaClass metaProp = metaClassForProperty(propertyName);
//递归查找id属性是否在Order中有效
metaProp.buildProperty(prop.getChildren(), builder);
}
} else {
//简单属性走这步,这也是递归的出口
String propertyName = reflector.findPropertyName(name);
if (propertyName != null) {
builder.append(propertyName);
}
}
//结果是order.id
return builder;
}
//根据属性的类型,创建对应的MetaClass对象。
public MetaClass metaClassForProperty(String name) {
Class> propType = reflector.getGetterType(name);
return MetaClass.forClass(propType, reflectorFactory);
}
hasGetter(name):判断复杂属性是否存在getter方法,如orders[0].id,先判断User中orders是否有getter方法,再判断Order中id是否有getter方法。
//以orders[0].id为例
public boolean hasGetter(String name) {
//name: orders, indexedName: orders[0], index: 0, children: id
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
//存在children,判断User的orders属性是否存在
if (reflector.hasGetter(prop.getName())) {
//判断orders属性的类型,注意我们这里希望查找到的是Order类型,而不是List类型
//因为id属性应该是在Order类中的。
MetaClass metaProp = metaClassForProperty(prop);
//递归判断children是否有getter方法
return metaProp.hasGetter(prop.getChildren());
} else {
return false;
}
} else {
//递归的出口
return reflector.hasGetter(prop.getName());
}
}
//获取orders的实际类型,根据此类型创建MetaClass对象。
private MetaClass metaClassForProperty(PropertyTokenizer prop) {
Class> propType = getGetterType(prop);
return MetaClass.forClass(propType, reflectorFactory);
}
//获取属性的getter方法返回类型
private Class> getGetterType(PropertyTokenizer prop) {
//type为集合类型,prop为orders[0]带有索引下标
Class> type = reflector.getGetterType(prop.getName());
if (prop.getIndex() != null && Collection.class.isAssignableFrom(type)) {
//获取orders的类型,应该是List
Type returnType = getGenericGetterType(prop.getName());
if (returnType instanceof ParameterizedType) {
//泛型的具体类型Order
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;
}
//如果属性orders有getter方法,TypeParameterResolver从getter方法中获取返回值类型
//属性无getter方法,TypeParameterResolver从orders字段定义中获取类型
private Type getGenericGetterType(String propertyName) {
try {
Invoker invoker = reflector.getGetInvoker(propertyName);
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 e) {
} catch (IllegalAccessException e) {
}
return null;
}
hasSetter(name):递归判断复杂属性是否有setter方法。
public boolean hasSetter(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
if (reflector.hasSetter(prop.getName())) {
MetaClass metaProp = metaClassForProperty(prop.getName());
return metaProp.hasSetter(prop.getChildren());
} else {
return false;
}
} else {
return reflector.hasSetter(prop.getName());
}
}
public MetaClass metaClassForProperty(String name) {
//直接从reflector中获取属性的类型
Class> propType = reflector.getGetterType(name);
return MetaClass.forClass(propType, reflectorFactory);
}
六、ObjectWrapper
通过ObjectWrapperFactory创建ObjectWrapper,ObjectWrapperFactory的实现类DefaultObjectWrapperFactory不可用,需要自己通过mybatis-config.xml扩展自定义的实现类。ObjectWrapper的实现类包含是BaseWrapper(抽象类)、CollectionWrapper。它们是解析复杂属性表达式的最终处理类,提供了set、get等方法。
BaseWrapper是抽象类,封装了MetaObject(解析复杂属性表达式解析类),其实现类包含BeanWrapper、MapWrapper。
BeanWrapper封装了Object object;MapWrapper封装了Map
复杂属性值的获取最终是从ObjectWrapper封装的对象中拿到的。
七、MetaObject
解析复杂属性表达式解析类,它描述了解析的过程。如orders[0].id; order.id; orders[0]等表达式的解析。在MetaObject中类级别的方法一般是调用MetaClass完成的,对象级别的方法一般配合ObjectWrapper完成。
public class MetaObject {
//原始javabean对象
private Object originalObject;
//objectWrapper对象,封装了originalObject
private ObjectWrapper objectWrapper;
//实例化originalObject的工厂类
private ObjectFactory objectFactory;
//创建objectWrapper的工厂对象
private ObjectWrapperFactory objectWrapperFactory;
//创建并缓存reflector的工厂对象
private ReflectorFactory reflectorFactory;
}