MyBatis源码之反射模块
封装了Java原生的反射, 并对其进行优化
1. Reflector
基础支持层, 包含整个MyBatis的基础模块, 为核心处理层提供良好的支持
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 public class Reflector { private static final MethodHandle isRecordMethodHandle = getIsRecordMethodHandle(); private final Class<?> type; private final String[] readablePropertyNames; private final String[] writablePropertyNames; private final Map<String, Invoker> setMethods = new HashMap <>(); private final Map<String, Invoker> getMethods = new HashMap <>(); private final Map<String, Class<?>> setTypes = new HashMap <>(); private final Map<String, Class<?>> getTypes = new HashMap <>(); private Constructor<?> defaultConstructor; private final Map<String, String> caseInsensitivePropertyMap = new HashMap <>(); public Reflector (Class<?> clazz) { type = clazz; addDefaultConstructor(clazz); Method[] classMethods = getClassMethods(clazz); if (isRecord(type)) { addRecordGetMethods(classMethods); } else { addGetMethods(classMethods); addSetMethods(classMethods); 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); } } }
1.1 addRecordGetMethods
#addDefaultConstructor(Class<?> clazz) 方法,查找默认无参构造方法
1 2 3 4 5 6 7 private void addDefaultConstructor (Class<?> clazz) { Constructor<?>[] constructors = clazz.getDeclaredConstructors(); Arrays.stream(constructors).filter(constructor -> constructor.getParameterTypes().length == 0 ).findAny() .ifPresent(constructor -> this .defaultConstructor = constructor); }
1.2 addGetMethods
#addGetMethods(Class<?> cls) 方法,初始化 getMethods 和 getTypes ,通过遍历 getting 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private void addGetMethods (Method[] methods) { Map<String, List<Method>> conflictingGetters = new HashMap <>(); Arrays.stream(methods).filter(m -> m.getParameterTypes().length == 0 && PropertyNamer.isGetter(m.getName())) .forEach(m -> addMethodConflict(conflictingGetters, PropertyNamer.methodToProperty(m.getName()), m)); resolveGetterConflicts(conflictingGetters); } private void addMethodConflict (Map<String, List<Method>> conflictingMethods, String name, Method method) { if (isValidPropertyName(name)) { List<Method> list = MapUtil.computeIfAbsent(conflictingMethods, name, k -> new ArrayList <>()); list.add(method); } }
1.3 getClassMethods
#getClassMethods(Class<?> cls) 方法,获得所有方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 private Method[] getClassMethods(Class<?> clazz) { Map<String, Method> uniqueMethods = new HashMap <>(); Class<?> currentClass = clazz; while (currentClass != null && currentClass != Object.class) { addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods()); 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 [0 ]); }private void addUniqueMethods (Map<String, Method> uniqueMethods, Method[] methods) { for (Method currentMethod : methods) { if (!currentMethod.isBridge()) { String signature = getSignature(currentMethod); if (!uniqueMethods.containsKey(signature)) { uniqueMethods.put(signature, currentMethod); } } } }private String getSignature (Method method) { StringBuilder sb = new StringBuilder (); Class<?> returnType = method.getReturnType(); sb.append(returnType.getName()).append('#' ); sb.append(method.getName()); Class<?>[] parameters = method.getParameterTypes(); for (int i = 0 ; i < parameters.length; i++) { sb.append(i == 0 ? ':' : ',' ).append(parameters[i].getName()); } return sb.toString(); }
1.4 resolveGetterConflicts
#resolveGetterConflicts(Map<String, List>) 方法,解决 getting 冲突方法。最终,一个属性,只保留一个对应的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 private void resolveGetterConflicts (Map<String, List<Method>> conflictingGetters) { for (Entry<String, List<Method>> entry : conflictingGetters.entrySet()) { Method winner = null ; String propName = entry.getKey(); boolean isAmbiguous = false ; 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)) { isAmbiguous = true ; break ; } if (candidate.getName().startsWith("is" )) { winner = candidate; } } else if (candidateType.isAssignableFrom(winnerType)) { } else if (winnerType.isAssignableFrom(candidateType)) { winner = candidate; } else { isAmbiguous = true ; break ; } } addGetMethod(propName, winner, isAmbiguous); } } private void addGetMethod (String name, Method method, boolean isAmbiguous) { MethodInvoker invoker = isAmbiguous ? new AmbiguousMethodInvoker (method, MessageFormat.format( "Illegal overloaded getter method with ambiguous type for property ''{0}'' in class ''{1}''. This breaks the JavaBeans specification and can cause unpredictable results." , name, method.getDeclaringClass().getName())) : new MethodInvoker (method); getMethods.put(name, invoker); Type returnType = TypeParameterResolver.resolveReturnType(method, type); getTypes.put(name, typeToClass(returnType)); }
1.5 addSetMethods
#addSetMethods(Class<?> cls) 方法,初始化 setMethods
和 setTypes
,通过遍历 setting 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 private void addSetMethods (Method[] methods) { Map<String, List<Method>> conflictingSetters = new HashMap <>(); Arrays.stream(methods).filter(m -> m.getParameterTypes().length == 1 && PropertyNamer.isSetter(m.getName())) .forEach(m -> addMethodConflict(conflictingSetters, PropertyNamer.methodToProperty(m.getName()), m)); resolveSetterConflicts(conflictingSetters); }private void resolveSetterConflicts (Map<String, List<Method>> conflictingSetters) { for (Entry<String, List<Method>> entry : conflictingSetters.entrySet()) { String propName = entry.getKey(); List<Method> setters = entry.getValue(); Class<?> getterType = getTypes.get(propName); boolean isGetterAmbiguous = getMethods.get(propName) instanceof AmbiguousMethodInvoker; boolean isSetterAmbiguous = false ; Method match = null ; for (Method setter : setters) { if (!isGetterAmbiguous && setter.getParameterTypes()[0 ].equals(getterType)) { match = setter; break ; } if (!isSetterAmbiguous) { match = pickBetterSetter(match, setter, propName); isSetterAmbiguous = match == null ; } } if (match != null ) { addSetMethod(propName, match); } } }private Method pickBetterSetter (Method setter1, Method setter2, String property) { if (setter1 == null ) { return setter2; } Class<?> paramType1 = setter1.getParameterTypes()[0 ]; Class<?> paramType2 = setter2.getParameterTypes()[0 ]; if (paramType1.isAssignableFrom(paramType2)) { return setter2; } if (paramType2.isAssignableFrom(paramType1)) { return setter1; } MethodInvoker invoker = new AmbiguousMethodInvoker (setter1, MessageFormat.format( "Ambiguous setters defined for property ''{0}'' in class ''{1}'' with types ''{2}'' and ''{3}''." , property, setter2.getDeclaringClass().getName(), paramType1.getName(), paramType2.getName())); setMethods.put(property, invoker); Type[] paramTypes = TypeParameterResolver.resolveParamTypes(setter1, type); setTypes.put(property, typeToClass(paramTypes[0 ])); return null ; }
1.6 addFields
#addFields(Class<?> clazz) 方法,初始化 getMethods
+ getTypes
和 setMethods
+ setTypes
,通过遍历 fields 属性。实际上,它是 #addGetMethods(…) 和 #addSetMethods(…) 方法的补充,因为有些 field ,不存在对应的 setting 或 getting 方法,所以直接使用对应的 field ,而不是方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 private void addFields (Class<?> clazz) { Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if (!setMethods.containsKey(field.getName())) { int modifiers = field.getModifiers(); if ((!Modifier.isFinal(modifiers) || !Modifier.isStatic(modifiers))) { addSetField(field); } } if (!getMethods.containsKey(field.getName())) { addGetField(field); } } if (clazz.getSuperclass() != null ) { addFields(clazz.getSuperclass()); } } private void addSetField (Field field) { if (isValidPropertyName(field.getName())) { setMethods.put(field.getName(), new SetFieldInvoker (field)); Type fieldType = TypeParameterResolver.resolveFieldType(field, type); setTypes.put(field.getName(), typeToClass(fieldType)); } } private void addGetField (Field field) { if (isValidPropertyName(field.getName())) { getMethods.put(field.getName(), new GetFieldInvoker (field)); Type fieldType = TypeParameterResolver.resolveFieldType(field, type); getTypes.put(field.getName(), typeToClass(fieldType)); } } private boolean isValidPropertyName (String name) { return (!name.startsWith("$" ) && !"serialVersionUID" .equals(name) && !"class" .equals(name)); }
2. ReflectorFactory
Reflector 工厂接口,用于创建和缓存 Reflector 对象, 所在包: org.apache.ibatis.reflection.ReflectorFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public interface ReflectorFactory { boolean isClassCacheEnabled () ; void setClassCacheEnabled (boolean classCacheEnabled) ; Reflector findForClass (Class<?> type) ; }
2.1 DefaultReflectorFactory
ReflectorFactory 默认的实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class DefaultReflectorFactory implements ReflectorFactory { private boolean classCacheEnabled = true ; private final ConcurrentMap<Class<?>, Reflector> reflectorMap = new ConcurrentHashMap <>(); 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) { return MapUtil.computeIfAbsent(reflectorMap, type, Reflector::new ); } return new Reflector (type); } }
3. Invoker
调用者接口, 所在包: org.apache.ibatis.reflection.invoker.Invoker
1 2 3 4 5 6 7 8 9 10 11 12 public interface Invoker { Object invoke (Object target, Object[] args) throws IllegalAccessException, InvocationTargetException; Class<?> getType(); }
3.1 GetFieldInvoker
实现 Invoker 接口,获得 Field 调用者, 所在包: org.apache.ibatis.reflection.invoker.GetFieldInvoker
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 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 { try { return field.get(target); } catch (IllegalAccessException e) { if (Reflector.canControlMemberAccessible()) { field.setAccessible(true ); return field.get(target); } throw e; } } @Override public Class<?> getType() { return field.getType(); } }
3.2 SetFieldInvoker
实现 Invoker 接口,设置 Field 调用者, 所在包: org.apache.ibatis.reflection.invoker.SetFieldInvoker
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 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 { try { field.set(target, args[0 ]); } catch (IllegalAccessException e) { if (!Reflector.canControlMemberAccessible()) { throw e; } field.setAccessible(true ); field.set(target, args[0 ]); } return null ; } @Override public Class<?> getType() { return field.getType(); } }
3.3 MethodInvoker
实现 Invoker 接口,指定方法的调用器, 所在包: org.apache.ibatis.reflection.invoker.MethodInvoker
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 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 ) { type = method.getParameterTypes()[0 ]; } else { type = method.getReturnType(); } } @Override public Object invoke (Object target, Object[] args) throws IllegalAccessException, InvocationTargetException { try { return method.invoke(target, args); } catch (IllegalAccessException e) { if (Reflector.canControlMemberAccessible()) { method.setAccessible(true ); return method.invoke(target, args); } throw e; } } @Override public Class<?> getType() { return type; } }
4. ObjectFactory
Object 工厂接口,用于创建指定类的对象, 所在包: org.apache.ibatis.reflection.factory.ObjectFactory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 public interface ObjectFactory { default void setProperties (Properties properties) { } <T> T create (Class<T> type) ; <T> T create (Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) ; <T> boolean isCollection (Class<T> type) ; }
4.1 DefaultObjectFactory
实现 ObjectFactory、Serializable 接口,ObjectFactory 默认实现类, 所在包: org.apache.ibatis.reflection.factory.DefaultObjectFactory
create
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 @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); } 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) { 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(); try { return constructor.newInstance(); } catch (IllegalAccessException e) { if (Reflector.canControlMemberAccessible()) { constructor.setAccessible(true ); return constructor.newInstance(); } throw e; } } constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class [0 ])); try { return constructor.newInstance(constructorArgs.toArray(new Object [0 ])); } catch (IllegalAccessException e) { if (Reflector.canControlMemberAccessible()) { constructor.setAccessible(true ); return constructor.newInstance(constructorArgs.toArray(new Object [0 ])); } throw e; } } catch (Exception e) { String argTypes = Optional.ofNullable(constructorArgTypes).orElseGet(Collections::emptyList).stream() .map(Class::getSimpleName).collect(Collectors.joining("," )); String argValues = Optional.ofNullable(constructorArgs).orElseGet(Collections::emptyList).stream() .map(String::valueOf).collect(Collectors.joining("," )); throw new ReflectionException ("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e); } }
isCollection
1 2 3 4 @Override public <T> boolean isCollection (Class<T> type) { return Collection.class.isAssignableFrom(type); }
5. Property 工具类
提供了 PropertyCopier、PropertyNamer、PropertyTokenizer 三个属性相关的工具类, 所在包: org.apache.ibatis.reflection.property
5.1 PropertyCopier
属性复制器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 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 { try { field.set(destinationBean, field.get(sourceBean)); } catch (IllegalAccessException e) { if (!Reflector.canControlMemberAccessible()) { throw e; } field.setAccessible(true ); field.set(destinationBean, field.get(sourceBean)); } } catch (Exception e) { } } parent = parent.getSuperclass(); } } }
5.2 PropertyNamer
属性名相关的工具类方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 public final class PropertyNamer { private PropertyNamer () { } public static String methodToProperty (String name) { if (name.startsWith("is" )) { name = name.substring(2 ); } else if (name.startsWith("get" ) || name.startsWith("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 isGetter(name) || isSetter(name); } public static boolean isGetter (String name) { return name.startsWith("get" ) && name.length() > 3 || name.startsWith("is" ) && name.length() > 2 ; } public static boolean isSetter (String name) { return name.startsWith("set" ) && name.length() > 3 ; } }
5.3 PropertyTokenizer
实现 Iterator 接口,属性分词器,支持迭代器的访问方式, 所在包: org.apache.ibatis.reflection.property.PropertyTokenizer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 public class PropertyTokenizer implements Iterator <PropertyTokenizer> { private String name; private final String indexedName; private String index; private final 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); } } 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." ); } }
类的元数据,基于 Reflector 和 PropertyTokenizer ,提供对指定类的各种操作, 所在包: org.apache.ibatis.reflection.MetaClass
构造方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 private final ReflectorFactory reflectorFactory;private final 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); } public MetaClass metaClassForProperty (String name) { Class<?> propType = reflector.getGetterType(name); return MetaClass.forClass(propType, reflectorFactory); }
findProperty
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 public String findProperty (String name, boolean useCamelCaseMapping) { if (useCamelCaseMapping) { name = name.replace("_" , "" ); } return findProperty(name); } 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) { PropertyTokenizer prop = new PropertyTokenizer (name); if (prop.hasNext()) { String propertyName = reflector.findPropertyName(prop.getName()); if (propertyName != null ) { builder.append(propertyName); builder.append("." ); MetaClass metaProp = metaClassForProperty(propertyName); metaProp.buildProperty(prop.getChildren(), builder); } } else { String propertyName = reflector.findPropertyName(name); if (propertyName != null ) { builder.append(propertyName); } } return builder; } public String findPropertyName (String name) { return caseInsensitivePropertyMap.get(name.toUpperCase(Locale.ENGLISH)); }
hasGetter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 public boolean hasGetter (String name) { PropertyTokenizer prop = new PropertyTokenizer (name); if (!prop.hasNext()) { return reflector.hasGetter(prop.getName()); } if (reflector.hasGetter(prop.getName())) { MetaClass metaProp = metaClassForProperty(prop); return metaProp.hasGetter(prop.getChildren()); } return false ; } private MetaClass metaClassForProperty (PropertyTokenizer prop) { Class<?> propType = getGetterType(prop); return MetaClass.forClass(propType, reflectorFactory); } 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; } private Type getGenericGetterType (String propertyName) { try { Invoker invoker = reflector.getGetInvoker(propertyName); if (invoker instanceof MethodInvoker) { Field declaredMethod = MethodInvoker.class.getDeclaredField("method" ); declaredMethod.setAccessible(true ); Method method = (Method) declaredMethod.get(invoker); return TypeParameterResolver.resolveReturnType(method, reflector.getType()); } if (invoker instanceof GetFieldInvoker) { Field declaredField = GetFieldInvoker.class.getDeclaredField("field" ); declaredField.setAccessible(true ); Field field = (Field) declaredField.get(invoker); return TypeParameterResolver.resolveFieldType(field, reflector.getType()); } } catch (NoSuchFieldException | IllegalAccessException e) { } return null ; }
getGetterType
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public Class<?> getGetterType(String name) { PropertyTokenizer prop = new PropertyTokenizer (name); if (prop.hasNext()) { MetaClass metaProp = metaClassForProperty(prop); return metaProp.getGetterType(prop.getChildren()); } return getGetterType(prop); }
7. ObjectWrapper
对象包装器接口,基于 MetaClass 工具类,定义对指定对象的各种操作 所在包: org.apache.ibatis.reflection.wrapper.ObjectWrapper
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 public interface ObjectWrapper { Object get (PropertyTokenizer prop) ; void set (PropertyTokenizer prop, Object value) ; String findProperty (String name, boolean useCamelCaseMapping) ; String[] getGetterNames(); String[] getSetterNames(); Class<?> getSetterType(String name); Class<?> getGetterType(String name); boolean hasSetter (String name) ; boolean hasGetter (String name) ; MetaObject instantiatePropertyValue (String name, PropertyTokenizer prop, ObjectFactory objectFactory) ; boolean isCollection () ; void add (Object element) ; <E> void addAll (List<E> element) ; }
7.1 BaseWrapper
实现 ObjectWrapper 接口,ObjectWrapper 抽象类,为子类 BeanWrapper 和 MapWrapper 提供属性值的获取和设置的公用方法, 所在包: org.apache.ibatis.reflection.wrapper.BaseWrapper
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 public abstract class BaseWrapper implements ObjectWrapper { protected static final Object[] NO_ARGUMENTS = {}; protected final MetaObject metaObject; protected BaseWrapper (MetaObject metaObject) { this .metaObject = metaObject; } protected Object resolveCollection (PropertyTokenizer prop, Object object) { if ("" .equals(prop.getName())) { return object; } return metaObject.getValue(prop.getName()); } protected Object getCollectionValue (PropertyTokenizer prop, Object collection) { if (collection == null ) { throw new ReflectionException ("Cannot get the value '" + prop.getIndexedName() + "' because the property '" + prop.getName() + "' is null." ); } if (collection instanceof Map) { return ((Map) collection).get(prop.getIndex()); } 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 ("Cannot get the value '" + prop.getIndexedName() + "' because the property '" + prop.getName() + "' is not Map, List or Array." ); } } protected void setCollectionValue (PropertyTokenizer prop, Object collection, Object value) { if (collection == null ) { throw new ReflectionException ("Cannot set the value '" + prop.getIndexedName() + "' because the property '" + prop.getName() + "' is null." ); } 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 ("Cannot set the value '" + prop.getIndexedName() + "' because the property '" + prop.getName() + "' is not Map, List or Array." ); } } } protected Object getChildValue (PropertyTokenizer prop) { MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName()); if (metaValue == SystemMetaObject.NULL_META_OBJECT) { return null ; } return metaValue.getValue(prop.getChildren()); } protected void setChildValue (PropertyTokenizer prop, Object value) { MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName()); if (metaValue == SystemMetaObject.NULL_META_OBJECT) { if (value == null ) { return ; } metaValue = instantiatePropertyValue(null , new PropertyTokenizer (prop.getName()), metaObject.getObjectFactory()); } metaValue.setValue(prop.getChildren(), value); } }
7.2 BeanWrapper
继承 BaseWrapper 抽象类,普通对象 的 ObjectWrapper 实现类,例如 User、Order 这样的 POJO 类, 所在包: org.apache.ibatis.reflection.wrapper.BeanWrapper
构造方法
1 2 3 4 5 6 7 8 9 10 11 12 private final Object object;private final MetaClass metaClass; public BeanWrapper (MetaObject metaObject, Object object) { super (metaObject); this .object = object; this .metaClass = MetaClass.forClass(object.getClass(), metaObject.getReflectorFactory()); }
get
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 @Override public Object get (PropertyTokenizer prop) { if (prop.hasNext()) { return getChildValue(prop); } else if (prop.getIndex() != null ) { return getCollectionValue(prop, resolveCollection(prop, object)); } else { return getBeanProperty(prop, object); } } 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); } }
set
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 @Override public void set (PropertyTokenizer prop, Object value) { if (prop.hasNext()) { setChildValue(prop, value); } else if (prop.getIndex() != null ) { setCollectionValue(prop, resolveCollection(prop, object), value); } else { setBeanProperty(prop, object, value); } } 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); } }