Reflection Toolbox
Reflector
Class Reflector a class corresponding to the object comprises:
//对应的Class类型
private final Class<?> type;
//可读属性(有get方法的)名字数组
private final String[] readablePropertyNames;
//可写属性(有set方法的)名字数组
private final String[] writeablePropertyNames;
//set方法,key为属性名称,value是Invoker对象(对set方法对应的method对象的封装)
private final Map<String, Invoker> setMethods = new HashMap<String, Invoker>();
//get方法
private final Map<String, Invoker> getMethods = new HashMap<String, Invoker>();
//set方法的参数类型
private final Map<String, Class<?>> setTypes = new HashMap<String, Class<?>>();
//get方法的返回值类型
private final Map<String, Class<?>> getTypes = new HashMap<String, Class<?>>();
//默认构造器
private Constructor<?> defaultConstructor;
//所有属性名称,全大写形式
private Map<String, String> caseInsensitivePropertyMap = new HashMap<String, String>();
More attributes will be filled in the constructor
public Reflector(Class<?> clazz) {
type = clazz;
addDefaultConstructor(clazz);
addGetMethods(clazz);
addSetMethods(clazz);
addFields(clazz);//没有set/get方法时会使用Field操作
readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]);
writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]);
for (String propName : readablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
for (String propName : writeablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
}
addGetMethods
private void addGetMethods(Class<?> cls) {
Map<String, List<Method>> conflictingGetters = new HashMap<String, List<Method>>();
Method[] methods = getClassMethods(cls);
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);
}
}
resolveGetterConflicts(conflictingGetters);
}
Which is shown in the flowchart in FIG.
ReflectorFactory
The main object is to create and provide Reflector cache, use concurrentMap cache object, key class
TypeParamterResolver
Type interface implementation class:
- Class
- ParameterizedType: parameterized type, such as
List<String>
- Type getRawType (): returns the original type parameters of types; as
List<String>
return List - Type [] getActualTypeArguments (): returns a list of the actual type or a variable type, such as
List<String>
return String - Type getOwnerType (): Return Type affiliations; as
A<T>
inner class classInner<T>
type ofA<T>
- Type getRawType (): returns the original type parameters of types; as
- GenericArrayType: an array type element, and is composed of TypeVariable or ParameterizedType; as
List<String>[]
- Type getGenericComponentType (): Returns an array of elements
- TypeVariable: type variable reaction JVM information before compiling the generic
- Type [] getBounds (): Get the type of the variable boundary, Object was not declared; The
Test<K extends Person>
upper boundary of K Persion - D getGenericDeclaration (): Get the type of the original variable type declaration; as
Test<K extends Person>
primitive types Test - String getName (): Gets the name when defined in the source code,
Test<K extends Person>
for K
- Type [] getBounds (): Get the type of the variable boundary, Object was not declared; The
- WildcardType: generics as a wildcard
? super Integer
- Type [] getUpperBounds (): returns the last variable paradigm
- Type [] getLowerBounds (): returns the next variable paradigm
ObjectFactory
The factory used to create objects, the default implementation DefaultObjectFactory
of its create () call instantiateClass()
, the final callConstructor.newInstance()
Property toolset
PropertyTokenizer
Responsible for parsing the expression, you can iteratePropertyNamer
Responsible for converting method name to the property name (remove is \ set \ get the prefix and the first letter lowercase, etc.) as well as to detect whether it is set, get a method or propertyPropertyCopier
Bean same type of copy attribute values, the method of the corecopyBeanProperties()
<resultMap id = "base" type="User">
<id column = "id" property="id"/>
<result column = "item" property="orders[0].items[0].name"/>
</result>
As shown in FIG decomposition
MetaClass
Use Reflector
and PropertyTokenizer
a combination of complex analytic expressions attribute
MetaClass
constructor receives a class of this class is constructed and Reflector
the object
MetaClass.findProperty()
will be called buildProperty()
, ultimately through PropertyTokenizer
analysis of complex property expression
PropertyTokenizer
supra analytical methods, MetaClass.hasGetter()
and MetaClass.hasSetter()
ultimately by Reflector
achieved
ObjectWrapper
MetaClass
Is a class-level meta-information processing and packaging, ObjectWrapper
packaging of an object, the query object defines a set of attributes, attribute update method
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);
}
As shown in FIG its successor UML
BaseWrapper is an abstract class that encapsulates MetaObject objects, and provides three methods
- getCollectionValue
- setCollectionValue
- resolverCollection: calls MetaObject.getValue ()
getCollectionValue will be based on the value of the index PropertyTokenizer
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.");
}
}
}
BeanWrapper aimed at javaBean
public Object get(PropertyTokenizer prop) {
//存在索引信息
if (prop.getIndex() != null) {
//拿到集合对象
Object collection = resolveCollection(prop, object);
//获取对应索引处的值
return getCollectionValue(prop, collection);
} else {
//通过metaClass操作反射get方法
return getBeanProperty(prop, object);
}
}
MetaObject
Complete the process of property expression parsing, the top
//原始JavaBean对象
private final Object originalObject;
//JavaBean的ObjectWrapper对象
private final ObjectWrapper objectWrapper;
//实例化originalObject的工厂
private final ObjectFactory objectFactory;
private final ObjectWrapperFactory objectWrapperFactory;
private final ReflectorFactory reflectorFactory;
MetaObject constructor creates a corresponding ObjectWrapper original objects based on object type and passed to achieve the ObjectFactory
MetaObject ObjectWrapper level and class of methods such as: hasGetter () are operated by MetaClass
object-level method such as: getValue by and with the realization of ObjectWrapper