Reflector是reflection包中最核心的一个类,负责对一个类的进行反射解析,并将解析后的结果存到属性中。
Reflector中的属性如下:
// 要被反射解析的类
private final Class<?> type;
// 能够读的属性列表,即有get方法的属性列表
private final String[] readablePropertyNames;
// 能够写的属性列表,即有set方法的属性列表
private final String[] writablePropertyNames;
// set方法映射表。键为属性名,值为对应的set方法
private final Map<String, Invoker> setMethods = new HashMap<>();
// get方法映射表。键为属性名,值为对应的get方法
private final Map<String, Invoker> getMethods = new HashMap<>();
// set方法输入类型。键为属性名,值为对应的该属性的set方法的类型(实际为set方法的第一个参数的类型)
private final Map<String, Class<?>> setTypes = new HashMap<>();
// get方法输出类型。键为属性名,值为对应的该属性的set方法的类型(实际为set方法的返回值类型)
private final Map<String, Class<?>> getTypes = new HashMap<>();
// 默认构造函数
private Constructor<?> defaultConstructor;
// 大小写无关的属性映射表。键为属性名全大写值,值为属性名
private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();
Reflector的反射解析实在构造器中进行的 ,会将该类的属性 方法等一一归类到属性中 如下所示:
/**
* Reflector的构造方法
* @param clazz 需要被反射处理的目标类
*/
public Reflector(Class<?> clazz) {
// 要被反射解析的类
type = clazz;
// 设置默认构造器属性
addDefaultConstructor(clazz);
// 解析所有的getter
addGetMethods(clazz);
// 解析所有有setter
addSetMethods(clazz);
// 解析所有属性
addFields(clazz);
// 设定可读属性
readablePropertyNames = getMethods.keySet().toArray(new String[0]);
// 设定可写属性
writablePropertyNames = setMethods.keySet().toArray(new String[0]);
// 将可读或者可写的属性放入大小写无关的属性映射表
for (String propName : readablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
for (String propName : writablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
}
分析一下addGetMethods的逻辑:
conflictingGetters的key是方法名解析后的属性名,V是对应的方法列表。同一个属性可能有多个方法 例如name属性对应 getName() isName() 两个方法,List<Method>里边就存了俩。
private void addGetMethods(Class<?> clazz) {
// 存储属性的get方法。Map的键为属性名,值为get方法列表。某个属性的get方法用列表存储是因为前期可能会为某一个属性找到多个可能get方法。
Map<String, List<Method>> conflictingGetters = new HashMap<>();
// 找出该类中所有的方法
Method[] methods = getClassMethods(clazz);
// 过滤出get方法,过滤条件有:无入参、符合Java Bean的命名规则;然后取出方法对应的属性名、方法,放入conflictingGetters
Arrays.stream(methods).filter(m -> m.getParameterTypes().length == 0 && PropertyNamer.isGetter(m.getName()))
.forEach(m -> addMethodConflict(conflictingGetters, PropertyNamer.methodToProperty(m.getName()), m));
// 如果一个属性有多个疑似get方法,resolveGetterConflicts用来找出合适的那个
resolveGetterConflicts(conflictingGetters);
}
resolveGetterConflicts用来处理多个疑似的get方法,如果一个属性有多个getter方法,该方法负责找出真正的 如果有重复get方法 返回值不一样 也不是继承关系 就会报错
// 如果一个属性有多个getter方法,该方法负责找出真正的 如果有重复get方法 返回值不一样 也不是继承关系 就会报错
private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {
for (Entry<String, List<Method>> entry : conflictingGetters.entrySet()) {
Method winner = null;
String propName = entry.getKey();
// 对key的多个getter进行循环
for (Method candidate : entry.getValue()) {
if (winner == null) {
// 第一个进来的方法
winner = candidate;
continue;
}
// 处理已经存好的方法,是暂时的胜出者
Class<?> winnerType = winner.getReturnType();
// 处理刚进入的方法,这是挑战者
Class<?> candidateType = candidate.getReturnType();
if (candidateType.equals(winnerType)) {
// 返回类型一样
if (!boolean.class.equals(candidateType)) {
// 不是布尔型,两个返回一样,则无法辨明到底哪个是getter
throw new ReflectionException(
"Illegal overloaded getter method with ambiguous type for property "
+ propName + " in class " + winner.getDeclaringClass()
+ ". This breaks the JavaBeans specification and can cause unpredictable results.");
} else if (candidate.getName().startsWith("is")) {
// 是is的当选
winner = candidate;
}
} else if (candidateType.isAssignableFrom(winnerType)) {
// candidateType返回了子类,则winner作为最终结果
} else if (winnerType.isAssignableFrom(candidateType)) {
// winner返回了子类,则candidate作为最终结果
winner = candidate;
} else {
throw new ReflectionException(
"Illegal overloaded getter method with ambiguous type for property "
+ propName + " in class " + winner.getDeclaringClass()
+ ". This breaks the JavaBeans specification and can cause unpredictable results.");
}
}
// 最后放入的是 属性:唯一的getter方法
addGetMethod(propName, winner);
}
}