ObjectWrapper
ObjectWrapper的主要作用就是对一个对象进行了包裹,方便通过这个类来对对象进行属性的设置以及读取属性
然后根据被包裹对象的类型,分别使用不同的子类来进行包裹
可以看到,主要有三种类型:
- BeanWrapper,主要处理Bean的属性读写
- MapWrapper,主要处理Map的属性读写
- CollectionWrapper,主要处理集合的属性读写
常用的方法如下
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);
}
BeanWrapper
构造函数
构造函数主要是赋值MetaObject,object以及根据Object的类型来获取MetaClass
public BeanWrapper(MetaObject metaObject, Object object) {
super(metaObject);
this.object = object;
this.metaClass = MetaClass.forClass(object.getClass(), metaObject.getReflectorFactory());
}
get
public Object get(PropertyTokenizer prop) {
// 当前遍历的属性包括下标,也就是是一个集合类的属性
if (prop.getIndex() != null) {
Object collection = resolveCollection(prop, object);
return getCollectionValue(prop, collection);
} else {
return getBeanProperty(prop, object);
}
}
这里首先看下如何处理集合类属性
比如我们当前需要解析的属性字符串是richList[0]
那么会将richList交给metaObject来解析,metaObject底层会通过objectWrapper来获取当前对象的richList属性,然后返回
protected Object resolveCollection(PropertyTokenizer prop, Object object) {
if ("".equals(prop.getName())) {
return object;
} else {
return metaObject.getValue(prop.getName());
}
}
接下来就是简单地case by case的处理,根据对象类型的不同,进行转换,然后获取指定下标的值
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.");
}
}
}
接下来看下当前遍历的属性不是集合类的情况,可以看到就是简单地通过MetaClass来获取对应属性的getter,然后执行,返回
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);
}
}
MetaObject
MetaObject中会使用到ObjectWrapper,因此接下来继续介绍下MetaObject
从之前的介绍可以看出,ObjectWrapper只是对一个对象的包括,并且可以对该对象的直接属性的读写,但是无法处理由.连接的属性链的读写
而MetaObject底层基于ObjectWrapper,提供了对使用.连接的属性链的读写
MetaObject主要完成的是对属性字符串的解析,负责顺着属性字符串进行遍历,但是最终返回值仍然是通过ObjectWrapper来获取的
构造函数
private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
// 原始的对象
this.originalObject = object;
// 负责根据参数来构建对象的工厂
this.objectFactory = objectFactory;
// 负责创建objectWraper的工厂,objectWraper可以通过传入PropertyTokenizer来对指定的属性进行读写
this.objectWrapperFactory = objectWrapperFactory;
// 负责创建reflector的工厂,reflector中封装了类的setter,getter和属性
this.reflectorFactory = reflectorFactory;
// 根据入参object的类型的不同,分别执行不同的操作,来对objectWrapper进行赋值
// 根据类型的不同,返回相应类型的objectWrapper
if (object instanceof ObjectWrapper) {
this.objectWrapper = (ObjectWrapper) object;
} else if (objectWrapperFactory.hasWrapperFor(object)) {
this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
} else if (object instanceof Map) {
this.objectWrapper = new MapWrapper(this, (Map) object);
} else if (object instanceof Collection) {
this.objectWrapper = new CollectionWrapper(this, (Collection) object);
} else {
this.objectWrapper = new BeanWrapper(this, object);
}
}
getValue
getValue用来根据字符串来获取对应的属性
主要原理就是递归地获取当前变量的属性的MetaClass,如果是表达式的最后一级,那么直接通过ObjectWrapper来返回结果
public Object getValue(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
// 递归入口
// 获取当前属性的MetaObject
MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
return null;
} else {
return metaValue.getValue(prop.getChildren());
}
} else {
// 递归出口
return objectWrapper.get(prop);
}
}
public MetaObject metaObjectForProperty(String name) {
Object value = getValue(name);
return MetaObject.forObject(value, objectFactory, objectWrapperFactory, reflectorFactory);
}
这里看个官方例子来增强理解
@Test
void shouldGetPropertyOfNullNestedProperty() {
MetaObject richWithNull = SystemMetaObject.forObject(new RichType());
assertNull(richWithNull.getValue("richType.richProperty"));
}
- 首先是创建一个MetaObject,因为当前RichType只是一个普通的类,所以最终创建的MetaObject具有的ObjectWrapper是BeanWrapper
- 当前需要解析的属性字符串是richType.richProperty,所以在getValue方法中首先会获取当前遍历的属性名称即richType,底层会通过BeanWrapper来获取当前对象的richType属性的值,然后使用这个值创建一个MetaObject,使用这个新创建的MetaObject,继续处理剩余的属性表达式即richProperty,过程和之前的一样,最终就会返回richProperty的值