1. 总览
Java 中的反射虽然功能强大,但对大多数开发人员来说,写出高质量的反射代码还是 有一定难度的。MyBatis 中专门提供了反射模块,该模块对 Java 原生的反射进行了良好的封装,提了更加简洁易用的 API,方便上层使调用,并且对反射操作进行了一系列优化,例如缓存了类的元数据,提高了反射操作的性能。
反射模块中涉及的类有30多个,但是都是属于比较简单的代码,我们一起来过一下吧。
由于反射模块涉及的解析太多,我会分为上下两篇来解析,第一篇主要是解析MyBatis支持反射的基础工具,第二篇主要解析MyBatis的Reflector
是如何使用这些基础工具,还有MetaClass
、MetaObject
等。
2. factory
org.apache.ibatis.reflection.factory
包下有两个类,分别是对象工厂接口ObjectFactory
及其实现类DefaultObjectFactory
。
2.1 ObjectFactory
那么我们首先来看看对象工厂的接口定义了些什么方法吧
/**
* MyBatis 对象工厂
*
* @author Clinton Begin
*/
public interface ObjectFactory {
/**
* 设置对象属性
* @param properties configuration properties
*/
void setProperties(Properties properties);
/**
* 使用默认构造器类实例化对象
* @param type Object type
* @return
*/
<T> T create(Class<T> type);
/**
* 使用指定的构造器及方法来实例化对象
* @param type Object type
* @param constructorArgTypes Constructor argument types
* @param constructorArgs Constructor argument values
* @return
*/
<T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);
/**
* 如果此对象可以有一组其他对象,则返回true。
* 它的主要目的是支持非java.util。集合对象,如Scala集合。
*
* @param type Object type
* @return whether it is a collection or not
* @since 3.1.0
*/
<T> boolean isCollection(Class<T> type);
}
对象工厂的接口主要定义了对象的创建和设置属性方法,还额外提供了一个判断是否为集合的接口。
2.2 DefaultObjectFactory
接下来看一下默认的实现类DefaultObjectFactory
提供的实现方法,首先是创建对象的方法:
@Override
public <T> T create(Class<T> type) {
return create(type, null, null);
}
@SuppressWarnings("unchecked")
@Override
public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
// 解析接口,主要是解析集合类接口,然后转化了默认的实现类
Class<?> classToCreate = resolveInterface(type);
// 实例化对象
return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
}
可以看到最终调用的实例化方法起那么是create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs)
,在该方法中,先解析创建的类型(如果是集合类的接口,则转换为默认的实现类),然后在跟进参数实例化对象:
- 解析接口
protected Class<?> resolveInterface(Class<?> type) {
Class<?> classToCreate;
if (type == List.class || type == Collection.class || type == Iterable.class) {
classToCreate = ArrayList.class;
} else if (type == Map.class) {
classToCreate = HashMap.class;
} else if (type == SortedSet.class) { // issue #510 Collections Support
classToCreate = TreeSet.class;
} else if (type == Set.class) {
classToCreate = HashSet.class;
} else {
classToCreate = type;
}
return classToCreate;
}
- 实例化对象
private <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
try {
Constructor<T> constructor;
if (constructorArgTypes == null || constructorArgs == null) {
// 使用默认构造器创建实例
constructor = type.getDeclaredConstructor();
if (!constructor.isAccessible()) {
constructor.setAccessible(true);
}
return constructor.newInstance();
}
// 使用指定的构造器创建实例
constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[constructorArgTypes.size()]));
if (!constructor.isAccessible()) {
constructor.setAccessible(true);
}
return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));
} catch (Exception e) {
// 输出异常信息
StringBuilder argTypes = new StringBuilder();
if (constructorArgTypes != null && !constructorArgTypes.isEmpty()) {
for (Class<?> argType : constructorArgTypes) {
argTypes.append(argType.getSimpleName());
argTypes.append(",");
}
argTypes.deleteCharAt(argTypes.length() - 1); // remove trailing ,
}
StringBuilder argValues = new StringBuilder();
if (constructorArgs != null && !constructorArgs.isEmpty()) {
for (Object argValue : constructorArgs) {
argValues.append(String.valueOf(argValue));
argValues.append(",");
}
argValues.deleteCharAt(argValues.length() - 1); // remove trailing ,
}
throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);
}
}
都是基础,大家看看就行。
3. invoker
org.apache.ibatis.reflection.invoker
包下定义了Invoker接口,用于标记之类提供可执行的方法调用接口,并提供了3个默认的实现类:MethodInvoker
、GetFieldInvoker
、SetFieldInvoker
,我们一个个来看吧。
3.1 Invoker
首先是Invoker接口,简单,不必多说。
public interface Invoker {
// 定义可执行的方法
Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;
// 获取该对象的真实类型
Class<?> getType();
}
3.2 MethodInvoker
然后是Invoker的实现类MethodInvoker
public class MethodInvoker implements Invoker {
private final Class<?> type;
private final Method method;
public MethodInvoker(Method method) {
this.method = method;
if (method.getParameterTypes().length == 1) {
// 对应的是set方法
type = method.getParameterTypes()[0];
} else {
// 对应的是get方法
type = method.getReturnType();
}
}
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
return method.invoke(target, args);
}
@Override
public Class<?> getType() {
return type;
}
}
- 代理调用被代理的方法,getType返回的类型由被代理的Method的参数而定
- 如果调用的方法为无参(一般是getXxx方法),则返回返回值的类型
- 如果调用的方法为有且只有一个参数(一般是setXxx方法),则返回调用参数的类型
3.3 GetFieldInvoker
public class GetFieldInvoker implements Invoker {
private final Field field;
public GetFieldInvoker(Field field) {
this.field = field;
}
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
return field.get(target);
}
@Override
public Class<?> getType() {
return field.getType();
}
}
简单,不必多说。
3.4 SetFieldInvoker
public class SetFieldInvoker implements Invoker {
private final Field field;
public SetFieldInvoker(Field field) {
this.field = field;
}
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {
field.set(target, args[0]);
return null;
}
@Override
public Class<?> getType() {
return field.getType();
}
}
简单,不必多说。
4. property
org.apache.ibatis.reflection.property
该包提供了三个操作属性的工具类,走起!
4.1 PropertyCopier
public final class PropertyCopier {
private PropertyCopier() {
// 私有化构造器
}
public static void copyBeanProperties(Class<?> type, Object sourceBean, Object destinationBean) {
Class<?> parent = type;
while (parent != null) {
final Field[] fields = parent.getDeclaredFields();
for(Field field : fields) {
try {
field.setAccessible(true);
field.set(destinationBean, field.get(sourceBean));
} catch (Exception e) {
// Nothing useful to do, will only fail on final fields, which will be ignored.
}
}
// 循环设置父类的属性
parent = parent.getSuperclass();
}
}
}
提供了属性复制的工具,可以看出来,这个是浅拷贝。
4.2 PropertyNamer
/**
* 对传入的属性名称进行判断,返回相关的结果
* @author Clinton Begin
*/
public final class PropertyNamer {
private PropertyNamer() {
// 私有化构造器
}
public static String methodToProperty(String name) {
if (name.startsWith("is")) {
// boolean
name = name.substring(2);
} else if (name.startsWith("get") || name.startsWith("set")) {
// get set 方法
name = name.substring(3);
} else {
throw new ReflectionException("Error parsing property name '" + name + "'. Didn't start with 'is', 'get' or 'set'.");
}
if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {
// 首字母转为小写
name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);
}
return name;
}
public static boolean isProperty(String name) {
return name.startsWith("get") || name.startsWith("set") || name.startsWith("is");
}
public static boolean isGetter(String name) {
return name.startsWith("get") || name.startsWith("is");
}
public static boolean isSetter(String name) {
return name.startsWith("set");
}
}
简单,不多说。
4.3 PropertyTokenizer
使用迭代器模式,对于给定的字符串进行迭代分词:
/**
* 使用迭代器模式,对于给定的字符串进行迭代分词
* @author Clinton Begin
*/
public class PropertyTokenizer implements Iterator<PropertyTokenizer> {
/**
* 解析后的第一级的属性名
*/
private String name;
/**
* 如果被解析的是数组,该值为数组的名称,如item[2],indexedName=item
*/
private final String indexedName;
/**
* 如果被解析的是数组,该值为属性所指向的元素索引,如item[2],index=2
*/
private String index;
/**
* 解析后的除了name外剩余的部分
*/
private final String children;
/**
* 参数分词
* 如fullname为item[1].name,则解析出来的
* name=item;
* indexedName=item[1];
* index=1;
* children=name
* @param fullname
*/
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;
}
/**
* 递归解析参数
* @return
*/
@Override
public PropertyTokenizer next() {
// 递归分析
return new PropertyTokenizer(children);
}
@Override
public void remove() {
// 不支持remove方法
throw new UnsupportedOperationException("Remove is not supported, as it has no meaning in the context of properties.");
}
}
注释写的比较详细,不多说了。
5. wrapper
org.apache.ibatis.reflection.wrapper
包下统一定义了对对象的反射操作Api,并对常用的Collection/Map/Bean做了默认实现。
该包下提供了两个接口和5个实现,我们先来看看接口的定义:
5.1 ObjectWrapper
public interface ObjectWrapper {
/**
* 通过给定的参数获取对象的值或属性
* @param prop
* @return
*/
Object get(PropertyTokenizer prop);
/**
* 通过给定的参数设置对象的值或属性
* @param prop
* @param value
*/
void set(PropertyTokenizer prop, Object value);
/**
* 查找是否有给定的属性
* @param name
* @param useCamelCaseMapping
* @return
*/
String findProperty(String name, boolean useCamelCaseMapping);
/**
* 获取所有的有getter方法的属性名
* @return
*/
String[] getGetterNames();
/**
* 获取所有的有setter方法的属性名
* @return
*/
String[] getSetterNames();
/**
* 获取指定属性的set参数类型
* @param name
* @return
*/
Class<?> getSetterType(String name);
/**
* 获取指定属性的返回参数类型
* @param name
* @return
*/
Class<?> getGetterType(String name);
/**
* 判断给定的属性是否有setter方法
* @param name
* @return
*/
boolean hasSetter(String name);
/**
* 判断给定的属性是否有getter方法
* @param name
* @return
*/
boolean hasGetter(String name);
/**
* 创建指定属性的值
* @param name
* @param prop
* @param objectFactory
* @return
*/
MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory);
/**
* 判断该包装类是否为集合类型
* @return
*/
boolean isCollection();
/**
* 集合类型专用方法,往集合中添加一个对象
* @param element
*/
void add(Object element);
/**
* 集合类型专用方法,往集合中添加一组对象
* @param element
* @param <E>
*/
<E> void addAll(List<E> element);
}
比较清晰,大家自己看看即可。
5.2 ObjectWrapperFactory
ObjectWrapper
的工厂接口,目前只有一个默认实现类:DefaultObjectWrapperFactory
,但是实际上默认情况下,我们是不使用 ObjectWrapperFactory
对象的。
public interface ObjectWrapperFactory {
/**
* 给定的对象是否已有ObjectWrapper的实例
* @param object
* @return
*/
boolean hasWrapperFor(Object object);
/**
* 根据实例获取ObjectWrapper
* @param metaObject
* @param object
* @return
*/
ObjectWrapper getWrapperFor(MetaObject metaObject, Object object);
}
5.3 BaseWrapper
两个接口说完后,我们来看看具体的实现,首先是BaseWrapper
,这是一个抽象类,实现并增强了ObjectWrapper
对集合类的操作。
/**
* 实现ObjectWrapper接口,扩展了集合的相关操作
* @author Clinton Begin
*/
public abstract class BaseWrapper implements ObjectWrapper {
protected static final Object[] NO_ARGUMENTS = new Object[0];
protected final MetaObject metaObject;
protected BaseWrapper(MetaObject metaObject) {
this.metaObject = metaObject;
}
/**
* 获得指定属性的值,如果不存在该属性则返回object对象
* @param prop
* @param object
* @return
*/
protected Object resolveCollection(PropertyTokenizer prop, Object object) {
if ("".equals(prop.getName())) {
return object;
} else {
return metaObject.getValue(prop.getName());
}
}
/**
* 获取集合类的某个值
* @param prop
* @param collection
* @return
*/
protected Object getCollectionValue(PropertyTokenizer prop, Object collection) {
if (collection instanceof Map) {
return ((Map) collection).get(prop.getIndex());
} else {
int i = Integer.parseInt(prop.getIndex());
if (collection instanceof List) {
return ((List) collection).get(i);
} else if (collection instanceof Object[]) {
return ((Object[]) collection)[i];
} else if (collection instanceof char[]) {
return ((char[]) collection)[i];
} else if (collection instanceof boolean[]) {
return ((boolean[]) collection)[i];
} else if (collection instanceof byte[]) {
return ((byte[]) collection)[i];
} else if (collection instanceof double[]) {
return ((double[]) collection)[i];
} else if (collection instanceof float[]) {
return ((float[]) collection)[i];
} else if (collection instanceof int[]) {
return ((int[]) collection)[i];
} else if (collection instanceof long[]) {
return ((long[]) collection)[i];
} else if (collection instanceof short[]) {
return ((short[]) collection)[i];
} else {
throw new ReflectionException("The '" + prop.getName() + "' property of " + collection + " is not a List or Array.");
}
}
}
/**
* 设值集合类
* @param prop
* @param collection
* @param value
*/
protected void setCollectionValue(PropertyTokenizer prop, Object collection, Object value) {
if (collection instanceof Map) {
((Map) collection).put(prop.getIndex(), value);
} else {
int i = Integer.parseInt(prop.getIndex());
if (collection instanceof List) {
((List) collection).set(i, value);
} else if (collection instanceof Object[]) {
((Object[]) collection)[i] = value;
} else if (collection instanceof char[]) {
((char[]) collection)[i] = (Character) value;
} else if (collection instanceof boolean[]) {
((boolean[]) collection)[i] = (Boolean) value;
} else if (collection instanceof byte[]) {
((byte[]) collection)[i] = (Byte) value;
} else if (collection instanceof double[]) {
((double[]) collection)[i] = (Double) value;
} else if (collection instanceof float[]) {
((float[]) collection)[i] = (Float) value;
} else if (collection instanceof int[]) {
((int[]) collection)[i] = (Integer) value;
} else if (collection instanceof long[]) {
((long[]) collection)[i] = (Long) value;
} else if (collection instanceof short[]) {
((short[]) collection)[i] = (Short) value;
} else {
throw new ReflectionException("The '" + prop.getName() + "' property of " + collection + " is not a List or Array.");
}
}
}
}
- 关于
MetaObject
的解析在后面的篇幅再做介绍。
5.4 BeanWrapper
java bean类型的ObjectWrapper
实现,对于ObjectWrapper
相关操作都代理到MetaClass
和MetaObject
上(关于这两个类下面再详细说明)。
代码比较多,但是都是很简单的,大家耐心看看就行。
public class BeanWrapper extends BaseWrapper {
/**
* 被代理的对象
*/
private final Object object;
/**
* 被代理对象的类的元数据
*/
private final MetaClass metaClass;
public BeanWrapper(MetaObject metaObject, Object object) {
super(metaObject);
this.object = object;
// 获取MetaClass实例
this.metaClass = MetaClass.forClass(object.getClass(), metaObject.getReflectorFactory());
}
@Override
public Object get(PropertyTokenizer prop) {
if (prop.getIndex() != null) {
// 集合类,调用BaseWrapper的相关方法
Object collection = resolveCollection(prop, object);
return getCollectionValue(prop, collection);
} else {
// 普通类
return getBeanProperty(prop, object);
}
}
@Override
public void set(PropertyTokenizer prop, Object value) {
if (prop.getIndex() != null) {
// 集合类,调用BaseWrapper的相关方法
Object collection = resolveCollection(prop, object);
setCollectionValue(prop, collection, value);
} else {
// 普通类
setBeanProperty(prop, object, value);
}
}
@Override
public String findProperty(String name, boolean useCamelCaseMapping) {
// 通过metaClass代理
return metaClass.findProperty(name, useCamelCaseMapping);
}
@Override
public String[] getGetterNames() {
// 通过metaClass代理
return metaClass.getGetterNames();
}
@Override
public String[] getSetterNames() {
// 通过metaClass代理
return metaClass.getSetterNames();
}
@Override
public Class<?> getSetterType(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
return metaClass.getSetterType(name);
} else {
// 递归获取最里层的setter,即item.order.name,获取的是name的类型
return metaValue.getSetterType(prop.getChildren());
}
} else {
return metaClass.getSetterType(name);
}
}
@Override
public Class<?> getGetterType(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
return metaClass.getGetterType(name);
} else {
// 递归获取最里层的getter,即item.order.name,获取的是name的类型
return metaValue.getGetterType(prop.getChildren());
}
} else {
return metaClass.getGetterType(name);
}
}
@Override
public boolean hasSetter(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
if (metaClass.hasSetter(prop.getIndexedName())) {
MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
// 递归判断
return metaClass.hasSetter(name);
} else {
return metaValue.hasSetter(prop.getChildren());
}
} else {
return false;
}
} else {
return metaClass.hasSetter(name);
}
}
@Override
public boolean hasGetter(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
if (metaClass.hasGetter(prop.getIndexedName())) {
MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
return metaClass.hasGetter(name);
} else {
// 递归判断
return metaValue.hasGetter(prop.getChildren());
}
} else {
return false;
}
} else {
return metaClass.hasGetter(name);
}
}
/**
* 实例化属性值
* @param name 属性名称
* @param prop
* @param objectFactory
* @return
*/
@Override
public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {
MetaObject metaValue;
// 解析类型
Class<?> type = getSetterType(prop.getName());
try {
// 使用对象工厂创建
Object newObject = objectFactory.create(type);
// 获取metaValue(MetaClass的实例)
metaValue = MetaObject.forObject(newObject, metaObject.getObjectFactory(), metaObject.getObjectWrapperFactory(), metaObject.getReflectorFactory());
// 设值
set(prop, newObject);
} catch (Exception e) {
throw new ReflectionException("Cannot set value of property '" + name + "' because '" + name + "' is null and cannot be instantiated on instance of " + type.getName() + ". Cause:" + e.toString(), e);
}
return metaValue;
}
// 获取属性值
private Object getBeanProperty(PropertyTokenizer prop, Object object) {
try {
Invoker method = metaClass.getGetInvoker(prop.getName());
try {
return method.invoke(object, NO_ARGUMENTS);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
} catch (RuntimeException e) {
throw e;
} catch (Throwable t) {
throw new ReflectionException("Could not get property '" + prop.getName() + "' from " + object.getClass() + ". Cause: " + t.toString(), t);
}
}
// 设置属性
private void setBeanProperty(PropertyTokenizer prop, Object object, Object value) {
try {
Invoker method = metaClass.getSetInvoker(prop.getName());
Object[] params = {value};
try {
method.invoke(object, params);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
} catch (Throwable t) {
throw new ReflectionException("Could not set property '" + prop.getName() + "' of '" + object.getClass() + "' with value '" + value + "' Cause: " + t.toString(), t);
}
}
@Override
public boolean isCollection() {
return false;
}
// bean 不支持集合操作
@Override
public void add(Object element) {
throw new UnsupportedOperationException();
}
// bean 不支持集合操作
@Override
public <E> void addAll(List<E> list) {
throw new UnsupportedOperationException();
}
}
5.5 CollectionWrapper
包装集合类数据,对于非集合类操作抛出不支持操作异常。
代码很简单。
public class CollectionWrapper implements ObjectWrapper {
private final Collection<Object> object;
public CollectionWrapper(MetaObject metaObject, Collection<Object> object) {
this.object = object;
}
@Override
public Object get(PropertyTokenizer prop) {
throw new UnsupportedOperationException();
}
@Override
public void set(PropertyTokenizer prop, Object value) {
throw new UnsupportedOperationException();
}
@Override
public String findProperty(String name, boolean useCamelCaseMapping) {
throw new UnsupportedOperationException();
}
@Override
public String[] getGetterNames() {
throw new UnsupportedOperationException();
}
@Override
public String[] getSetterNames() {
throw new UnsupportedOperationException();
}
@Override
public Class<?> getSetterType(String name) {
throw new UnsupportedOperationException();
}
@Override
public Class<?> getGetterType(String name) {
throw new UnsupportedOperationException();
}
@Override
public boolean hasSetter(String name) {
throw new UnsupportedOperationException();
}
@Override
public boolean hasGetter(String name) {
throw new UnsupportedOperationException();
}
@Override
public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {
throw new UnsupportedOperationException();
}
@Override
public boolean isCollection() {
return true;
}
@Override
public void add(Object element) {
object.add(element);
}
@Override
public <E> void addAll(List<E> element) {
object.addAll(element);
}
}
5.6 DefaultObjectWrapperFactory
该类默认不会使用,了解一下即可。
public class DefaultObjectWrapperFactory implements ObjectWrapperFactory {
@Override
public boolean hasWrapperFor(Object object) {
return false;
}
@Override
public ObjectWrapper getWrapperFor(MetaObject metaObject, Object object) {
throw new ReflectionException("The DefaultObjectWrapperFactory should never be called to provide an ObjectWrapper.");
}
}
6. reflection
6.1 ArrayUtil
/**
* 提供可以处理数组的hashCode、equals和toString方法。
*/
public class ArrayUtil {
/**
* 返回对象的hashCode,如果是null则返回0,
* 如果是非集合,则返回该对象的hashCode,
* 如果是集合这通过Arrays工具类获取该集合的hashCode
*/
public static int hashCode(Object obj) {
if (obj == null) {
// for consistency with Arrays#hashCode() and Objects#hashCode()
return 0;
}
final Class<?> clazz = obj.getClass();
if (!clazz.isArray()) {
return obj.hashCode();
}
final Class<?> componentType = clazz.getComponentType();
if (long.class.equals(componentType)) {
return Arrays.hashCode((long[]) obj);
} else if (int.class.equals(componentType)) {
return Arrays.hashCode((int[]) obj);
} else if (short.class.equals(componentType)) {
return Arrays.hashCode((short[]) obj);
} else if (char.class.equals(componentType)) {
return Arrays.hashCode((char[]) obj);
} else if (byte.class.equals(componentType)) {
return Arrays.hashCode((byte[]) obj);
} else if (boolean.class.equals(componentType)) {
return Arrays.hashCode((boolean[]) obj);
} else if (float.class.equals(componentType)) {
return Arrays.hashCode((float[]) obj);
} else if (double.class.equals(componentType)) {
return Arrays.hashCode((double[]) obj);
} else {
return Arrays.hashCode((Object[]) obj);
}
}
/**
* 判断两个对象是否相等,同样如果是结合类型,则委托给Arrays工具类进行判断
*/
public static boolean equals(Object thisObj, Object thatObj) {
if (thisObj == null) {
return thatObj == null;
} else if (thatObj == null) {
return false;
}
final Class<?> clazz = thisObj.getClass();
if (!clazz.equals(thatObj.getClass())) {
return false;
}
if (!clazz.isArray()) {
return thisObj.equals(thatObj);
}
final Class<?> componentType = clazz.getComponentType();
if (long.class.equals(componentType)) {
return Arrays.equals((long[]) thisObj, (long[]) thatObj);
} else if (int.class.equals(componentType)) {
return Arrays.equals((int[]) thisObj, (int[]) thatObj);
} else if (short.class.equals(componentType)) {
return Arrays.equals((short[]) thisObj, (short[]) thatObj);
} else if (char.class.equals(componentType)) {
return Arrays.equals((char[]) thisObj, (char[]) thatObj);
} else if (byte.class.equals(componentType)) {
return Arrays.equals((byte[]) thisObj, (byte[]) thatObj);
} else if (boolean.class.equals(componentType)) {
return Arrays.equals((boolean[]) thisObj, (boolean[]) thatObj);
} else if (float.class.equals(componentType)) {
return Arrays.equals((float[]) thisObj, (float[]) thatObj);
} else if (double.class.equals(componentType)) {
return Arrays.equals((double[]) thisObj, (double[]) thatObj);
} else {
return Arrays.equals((Object[]) thisObj, (Object[]) thatObj);
}
}
/**
* 打印对象,同样如果是结合类型,则委托给Arrays工具类进行判断
*/
public static String toString(Object obj) {
if (obj == null) {
return "null";
}
final Class<?> clazz = obj.getClass();
if (!clazz.isArray()) {
return obj.toString();
}
final Class<?> componentType = obj.getClass().getComponentType();
if (long.class.equals(componentType)) {
return Arrays.toString((long[]) obj);
} else if (int.class.equals(componentType)) {
return Arrays.toString((int[]) obj);
} else if (short.class.equals(componentType)) {
return Arrays.toString((short[]) obj);
} else if (char.class.equals(componentType)) {
return Arrays.toString((char[]) obj);
} else if (byte.class.equals(componentType)) {
return Arrays.toString((byte[]) obj);
} else if (boolean.class.equals(componentType)) {
return Arrays.toString((boolean[]) obj);
} else if (float.class.equals(componentType)) {
return Arrays.toString((float[]) obj);
} else if (double.class.equals(componentType)) {
return Arrays.toString((double[]) obj);
} else {
return Arrays.toString((Object[]) obj);
}
}
}
提供了数组增强的工具类。
6.2 ExceptionUtil
public class ExceptionUtil {
private ExceptionUtil() {
// Prevent Instantiation
}
// 异常处理工具类,用于对InvocationTargetException和UndeclaredThrowableException两种异常的解包,获取真实异常对象。
public static Throwable unwrapThrowable(Throwable wrapped) {
Throwable unwrapped = wrapped;
while (true) {
if (unwrapped instanceof InvocationTargetException) {
unwrapped = ((InvocationTargetException) unwrapped).getTargetException();
} else if (unwrapped instanceof UndeclaredThrowableException) {
unwrapped = ((UndeclaredThrowableException) unwrapped).getUndeclaredThrowable();
} else {
return unwrapped;
}
}
}
}
6.3 Jdk
用于判断当前Jdk版本是否包含java.lang.reflect.Parameter
和 java.time.Clock
两个类,jdk1.8+提供的类。
public class Jdk {
/**
* 是否支持java.lang.reflect.Parameter
*/
public static final boolean parameterExists;
static {
boolean available = false;
try {
Resources.classForName("java.lang.reflect.Parameter");
available = true;
} catch (ClassNotFoundException e) {
// ignore
}
parameterExists = available;
}
/**
* 是否支持java.time.Clock
*/
public static final boolean dateAndTimeApiExists;
static {
boolean available = false;
try {
Resources.classForName("java.time.Clock");
available = true;
} catch (ClassNotFoundException e) {
// ignore
}
dateAndTimeApiExists = available;
}
private Jdk() {
super();
}
}
6.4 ParamNameUtil
/**
* 获取方法或构造器的参数信息
*/
@UsesJava8
public class ParamNameUtil {
public static List<String> getParamNames(Method method) {
return getParameterNames(method);
}
public static List<String> getParamNames(Constructor<?> constructor) {
return getParameterNames(constructor);
}
private static List<String> getParameterNames(Executable executable) {
final List<String> names = new ArrayList<String>();
final Parameter[] params = executable.getParameters();
for (Parameter param : params) {
names.add(param.getName());
}
return names;
}
private ParamNameUtil() {
super();
}
}
该方法需要jdk1.8支持。
6.5 ParamNameResolver
ParamNameResolver
是方法参数名称的解析器,用于解析方法的参数名称,如果配置了useActualParamName
(默认为true
)且jdk为1.8及以上,不使用@Params注解也可直接获取接口上的参数名称,否在对于不适用@Params注解的参数,会默认生成param1,param2…
先看看它的关键属性:
/**
* 通用参数的前缀
*/
private static final String GENERIC_NAME_PREFIX = "param";
/**
* key是参数的索引,value是参数解析后的值
* 如果使用{@link Param}指定,则value从注解中获取名称。
* 当没有指定{@link Param}时,使用参数索引作为值。
* 注意当方法具有特殊参数时(例如{@link RowBounds}或{@link ResultHandler}),这个索引可能与实际索引不同
*/
private final SortedMap<Integer, String> names;
/**
* 标记是否使用了{@link Param}注解
*/
private boolean hasParamAnnotation;
其中names
是解析的中间结果,其key是参数的索引,value是参数解析后的值。
先看看它的构造器:
public ParamNameResolver(Configuration config, Method method) {
final Class<?>[] paramTypes = method.getParameterTypes();
final Annotation[][] paramAnnotations = method.getParameterAnnotations();
final SortedMap<Integer, String> map = new TreeMap<Integer, String>();
int paramCount = paramAnnotations.length;
// 从@Param注释获取属性名称
for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
if (isSpecialParameter(paramTypes[paramIndex])) {
// <1>跳过RowBounds和ResultHandler类型的参数
continue;
}
// 解析是否有被@Param注解的参数
String name = null;
for (Annotation annotation : paramAnnotations[paramIndex]) {
if (annotation instanceof Param) {
hasParamAnnotation = true;
name = ((Param) annotation).value();
break;
}
}
if (name == null) {
// 没有指定@Param注解
// 是否使用参数名称,这个配置默认是开启的
if (config.isUseActualParamName()) {
// <2>通过Jdk8的Parameter api获取参数名称
name = getActualParamName(method, paramIndex);
}
if (name == null) {
// use the parameter index as the name ("0", "1", ...)
// gcode issue #71
// 如果即没指定参数名称,又不能获取到参数的名称,则使用参数索引作为名称
name = String.valueOf(map.size());
}
}
map.put(paramIndex, name);
}
// 最后转换为一个不可修改的SortedMap赋值给names
names = Collections.unmodifiableSortedMap(map);
}
- <1> 处判断参数是否为需要跳过的特殊类型
private static boolean isSpecialParameter(Class<?> clazz) { return RowBounds.class.isAssignableFrom(clazz) || ResultHandler.class.isAssignableFrom(clazz); }
跳过了
RowBounds
和ResultHandler
类型的参数 - <2> 处通过Jdk8的Parameter api获取参数名称
/** * 通过Jdk8的Parameter api获取参数名称 * @param method * @param paramIndex * @return */ private String getActualParamName(Method method, int paramIndex) { if (Jdk.parameterExists) { return ParamNameUtil.getParamNames(method).get(paramIndex); } return null; }
其中
Jdk
和ParamNameUtil
在前面的篇幅已经介绍过啦。
通过上面的构造器,我们举个栗子:
method(@Param("M") int a, @Param("N") int b)
- 解析后生成的Map为:
{{0, "M"}, {1, "N"}}
- 解析后生成的Map为:
method(int a, int b)
- 解析后生成的Map为:
{{0, "0"}, {1, "1"}}
- 解析后生成的Map为:
method(int a, RowBounds rb, int b)
- 解析后生成的Map为:
{{0, "0"}, {2, "1"}}
- 解析后生成的Map为:
除此之外,ParamNameResolver
还提供了一个获取解析后的参数映射方法:
public Object getNamedParams(Object[] args) {
final int paramCount = names.size();
if (args == null || paramCount == 0) {
return null;
} else if (!hasParamAnnotation && paramCount == 1) {
return args[names.firstKey()];
} else {
final Map<String, Object> param = new ParamMap<Object>();
int i = 0;
for (Map.Entry<Integer, String> entry : names.entrySet()) {
param.put(entry.getValue(), args[entry.getKey()]);
// 加入通用的参数,即param1,param2等
final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);
// 避免通用的参数覆盖
if (!names.containsValue(genericParamName)) {
param.put(genericParamName, args[entry.getKey()]);
}
i++;
}
return param;
}
}
这个方法虽然很简单,但是很关键哦,在以后讲解的MapperMethod
类中负责吧方法参数转换为mapper中的参数替换,即#{key} / ${key}
6.6 TypeParameterResolver
TypeParameterResolver
暴露了三个公用静态方法,分别用于 Field 、Method 返回类型、Method 参数的泛型解析。我们先来瞅一瞅
/**
* 把泛型字段解析为实际运行时的类型
*/
public static Type resolveFieldType(Field field, Type srcType) {
// 获取字段的泛型定义
Type fieldType = field.getGenericType();
// 获取该字段所在定义类的类型
Class<?> declaringClass = field.getDeclaringClass();
// 解析方法
return resolveType(fieldType, srcType, declaringClass);
}
/**
* 把泛型返回类型解析为实际运行时的类型
*/
public static Type resolveReturnType(Method method, Type srcType) {
// 获取返回类型的泛型定义
Type returnType = method.getGenericReturnType();
// 获取该方法所在类的类型
Class<?> declaringClass = method.getDeclaringClass();
// 解析方法
return resolveType(returnType, srcType, declaringClass);
}
/**
* 把泛型方法参数解析为实际运行时的类型
*/
public static Type[] resolveParamTypes(Method method, Type srcType) {
// 获取泛型参数
Type[] paramTypes = method.getGenericParameterTypes();
// 获取该方法所在类的类型
Class<?> declaringClass = method.getDeclaringClass();
Type[] result = new Type[paramTypes.length];
for (int i = 0; i < paramTypes.length; i++) {
// 解析方法
result[i] = resolveType(paramTypes[i], srcType, declaringClass);
}
return result;
}
上面涉及到Java Type相关的操作,如果不熟悉的同学可以先看看这篇《Java中的Type详解》。
可见,实际执行类型解析的是resolveType(Type type, Type srcType, Class<?> 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;
}
}
6.6.1 resolveGenericArrayType
我们先来看看比较简单的泛型数组参数解析resolveGenericArrayType
/**
* 解析泛型数组类型
* @param genericArrayType
* @param srcType
* @param declaringClass
* @return
*/
private static Type resolveGenericArrayType(GenericArrayType genericArrayType, Type srcType, Class<?> declaringClass) {
// 获取数组参数的元素类型
Type componentType = genericArrayType.getGenericComponentType();
Type resolvedComponentType = null;
if (componentType instanceof TypeVariable) {
// 如果是泛型变量,则调用泛型调用的解析方法
resolvedComponentType = resolveTypeVar((TypeVariable<?>) componentType, srcType, declaringClass);
} else if (componentType instanceof GenericArrayType) {
// 如果还是泛型数组,则递归解析
resolvedComponentType = resolveGenericArrayType((GenericArrayType) componentType, srcType, declaringClass);
} else if (componentType instanceof ParameterizedType) {
// 如果是参数化泛型
resolvedComponentType = resolveParameterizedType((ParameterizedType) componentType, srcType, declaringClass);
}
if (resolvedComponentType instanceof Class) {
// 如果解析出来的是Class类型,则返回该类型的数组的类对象
return Array.newInstance((Class<?>) resolvedComponentType, 0).getClass();
} else {
// 返回GenericArrayType的实现类
return new GenericArrayTypeImpl(resolvedComponentType);
}
}
/**
* 泛型数组类型,用来描述 ParameterizedType、TypeVariable 类型的数组;即 List<T>[]、T[] 等;
*/
static class GenericArrayTypeImpl implements GenericArrayType {
private Type genericComponentType;
private GenericArrayTypeImpl(Type genericComponentType) {
super();
this.genericComponentType = genericComponentType;
}
@Override
public Type getGenericComponentType() {
return genericComponentType;
}
}
注释比较详细,先获取泛型数组中的元素类型,然后根据类型做对应的解析。
6.6.2 resolveParameterizedType
/**
* 解析参数化泛型
* @param parameterizedType
* @param srcType
* @param declaringClass
* @return
*/
private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type srcType, Class<?> declaringClass) {
// 获取原始类型,如Map、List等
Class<?> rawType = (Class<?>) parameterizedType.getRawType();
// 获取实际泛型类型,对于Map<String, Object> 则返回String和Object的Tyle
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) {
// 解析通配符泛型,如<? extends Object>
args[i] = resolveWildcardType((WildcardType) typeArgs[i], srcType, declaringClass);
} else {
// 如果不是泛型则直接返回
args[i] = typeArgs[i];
}
}
return new ParameterizedTypeImpl(rawType, null, args);
}
套路跟resolveGenericArrayType
类似,具体解析交由resolveTypeVar
或者resolveWildcardType
/**
* 解析通配符泛型
* 现阶段通配符只接受一个上边界或下边界, 返回数组是为了以后的扩展, 实际上现在返回的数组的大小是1
* @param wildcardType
* @param srcType
* @param declaringClass
* @return
*/
private static Type resolveWildcardType(WildcardType wildcardType, Type srcType, Class<?> declaringClass) {
// 解析下边界,注意<? extends Object> 这种是没有下边界的,<? super Object> 才有
Type[] lowerBounds = resolveWildcardTypeBounds(wildcardType.getLowerBounds(), srcType, declaringClass);
// 解析上边界,<? extends String>,上边界一般都是Object,下边界为String
Type[] upperBounds = resolveWildcardTypeBounds(wildcardType.getUpperBounds(), srcType, declaringClass);
return new WildcardTypeImpl(lowerBounds, upperBounds);
}
/**
* 解析通配符泛型的边界
* @param bounds
* @param srcType
* @param declaringClass
* @return
*/
private static Type[] resolveWildcardTypeBounds(Type[] bounds, Type srcType, Class<?> declaringClass) {
Type[] result = new Type[bounds.length];
for (int i = 0; i < bounds.length; i++) {
if (bounds[i] instanceof TypeVariable) {
// 解析泛型变量
result[i] = resolveTypeVar((TypeVariable<?>) bounds[i], srcType, declaringClass);
} else if (bounds[i] instanceof ParameterizedType) {
// 解析参数化泛型
result[i] = resolveParameterizedType((ParameterizedType) bounds[i], srcType, declaringClass);
} else if (bounds[i] instanceof WildcardType) {
// 解析通配符泛型
result[i] = resolveWildcardType((WildcardType) bounds[i], srcType, declaringClass);
} else {
result[i] = bounds[i];
}
}
return result;
}
看resolveWildcardTypeBounds
是不是相同的套路。
还有ParameterizedTypeImpl
和WildcardTypeImpl
也类似:
/**
* 参数化类型,即泛型。例如:List<T>、Map<K, V>等带有参数化的配置
*/
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) + "]";
}
}
/**
* 泛型表达式(或者通配符表达式),即 ? extend Number、? super Integer 这样的表达式。
*/
static class WildcardTypeImpl implements WildcardType {
private Type[] lowerBounds;
private Type[] upperBounds;
private WildcardTypeImpl(Type[] lowerBounds, Type[] upperBounds) {
super();
this.lowerBounds = lowerBounds;
this.upperBounds = upperBounds;
}
@Override
public Type[] getLowerBounds() {
return lowerBounds;
}
@Override
public Type[] getUpperBounds() {
return upperBounds;
}
}
6.6.3 resolveTypeVar
接下来就看看泛型参数解析器的核心方法:
/**
* 解析泛型变量
* @param typeVar
* @param srcType
* @param declaringClass
* @return
*/
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) {
// 如果传入的是参数化的泛型,则取参数化泛型的承载类
ParameterizedType parameterizedType = (ParameterizedType) srcType;
clazz = (Class<?>) parameterizedType.getRawType();
} else {
throw new IllegalArgumentException("The 2nd arg must be Class or ParameterizedType, but was: " + srcType.getClass());
}
// 如果来源类型就在定义类,那么取定义类上的边界即可
if (clazz == declaringClass) {
Type[] bounds = typeVar.getBounds();
if(bounds.length > 0) {
return bounds[0];
}
return Object.class;
}
// 否则查询带有泛型的父类
Type superclass = clazz.getGenericSuperclass();
// 从父类中计算运行时类型
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;
}
}
// 如果都找不到就返回Object类
return Object.class;
}
逻辑不饶,看看注释即可,先从定义类》父类》接口的顺序查找。对于父类和接口的查找,我们来看看scanSuperTypes
是如何扫描的:
/**
* 扫描父类,计算指定变量类型的运行时类型
* @param typeVar
* @param srcType
* @param declaringClass
* @param clazz
* @param superclass
* @return
*/
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) {
// 找到传入的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)) {
// 父类的原始类型与定义类型不一致,可能是父类的父类,递归调用resolveTypeVar来解析
result = resolveTypeVar(typeVar, parentAsType, declaringClass);
}
} else if (superclass instanceof Class) {
// 父类是实际类型
if (declaringClass.isAssignableFrom((Class<?>) superclass)) {
// 递归调用resolveTypeVar来解析
result = resolveTypeVar(typeVar, superclass, declaringClass);
}
}
return result;
}
这一段可能不太好理解,需要有Java反射操作泛型有一定基础才能比较容易掌握,各位可以结合注释好好琢磨一下。