【深入理解MyBatis】- 07Mybatis 反射器Reflector源码

反射器类Reflector结构

【深入理解MyBatis】- 07Mybatis 反射器Reflector源码_第1张图片

Reflector反射器类对Class type字段、方法封装,依赖于java Class对象实现,上述图片为Reflector结构关系,主要是将对象字段、方法封装起来

Reflector源码分析

public class Reflector {
  private final Class<?> type;
  private final String[] readablePropertyNames;
  private final String[] writeablePropertyNames;
  private final Map<String, Invoker> setMethods = new HashMap<String, Invoker>();
  private final Map<String, Invoker> getMethods = new HashMap<String, Invoker>();
  private final Map<String, Class<?>> setTypes = new HashMap<String, Class<?>>();
  private final Map<String, Class<?>> getTypes = new HashMap<String, Class<?>>();
  private Constructor<?> defaultConstructor;

  private Map<String, String> caseInsensitivePropertyMap = new HashMap<String, String>();
}

主要从Reflector 几个属性的角度为阅读源码,分而治之

addGetMethods/getTypes属性源码

setMethods属性的入口:方法addGetMethods

	private void addGetMethods(Class<?> type) {
		Map<String, List<Method>> conflictingGetters = new HashMap<String, List<Method>>();
		// 1. 获取Class type所有方法,包括所有私有方法,继承方法,实现接口方法
		Method[] methods = getClassMethods(type);
		for (Method method : methods) {
			if (method.getParameterTypes().length > 0) {
				continue;
			}
			String name = method.getName();
			if ((name.startsWith("get") && name.length() > 3) || (name.startsWith("is") && name.length() > 2)) {
				name = PropertyNamer.methodToProperty(name);
				addMethodConflict(conflictingGetters, name, method);
			}
		}
		
		// 2. 由于Java反射中method.isBridge() 桥接方法的存在,需要去重
		resolveGetterConflicts(conflictingGetters);
	}

获取Class type所有方法的实现

	private Method[] getClassMethods(Class<?> type) {
		Map<String, Method> uniqueMethods = new HashMap<String, Method>();
		Class<?> currentClass = type;
		while (currentClass != null && currentClass != Object.class) {
			addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());

			// 当Class type是一个抽象方法时,需要找出其实现的接口方法
			Class<?>[] interfaces = currentClass.getInterfaces();
			for (Class<?> anInterface : interfaces) {
				addUniqueMethods(uniqueMethods, anInterface.getMethods());
			}

			// 赋值给继承的父类
			currentClass = currentClass.getSuperclass();
		}

		Collection<Method> methods = uniqueMethods.values();

		return methods.toArray(new Method[methods.size()]);
	}

过滤父类同名方法,保留子类方法,通过A.isAssignableFrom(B), 判断A是否为B的父类

	private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {
		for (Entry<String, List<Method>> entry : conflictingGetters.entrySet()) {
			Method winner = null;
			String propName = entry.getKey();
			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)) {
						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")) {
						winner = candidate;
					}
				} else if (candidateType.isAssignableFrom(winnerType)) {
					// OK getter type is descendant
				} else if (winnerType.isAssignableFrom(candidateType)) {
					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.");
				}
			}
			
			// 保存addGetMethods属性
			addGetMethod(propName, winner);
		}
	}

保存addGetMethods属性

  private void addGetMethod(String name, Method method) {
    if (isValidPropertyName(name)) {
      getMethods.put(name, new MethodInvoker(method));
      Type returnType = TypeParameterResolver.resolveReturnType(method, type);
      getTypes.put(name, typeToClass(returnType));
    }
  }

addGetMethods/getTypes属性源码

待续…

你可能感兴趣的:(深入理解MyBatis)