前段时间做公司业务, 刚好遇到场景要动态获取Pojo类, 然后作一些运算, 再赋值到另一个类上, 立即想到用反射来解决, 但自己写的需要写一大堆代码, 而且自己感觉写得不是太好, 想着有没有第三方已经封装好的api可以用呢? 刚好想到 Mybatis是利用 MetaObject做ORM处理, 可以借来用用 (Mybatis的源码没白读哈)。用是用得挺爽, 但在想MetaObject是怎么做到可以像动态语言般来处理Pojo类呢? 因此决定去认真读一下它的源码。
先写一个示例看看:
package com.example.metdobjectanalysis.model;
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
-------
package com.example.metdobjectanalysis;
import com.example.metdobjectanalysis.model.Person;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class MetdObjectAnalysisApplicationTests {
@Test
void getTest() {
Person person = new Person();
MetaObject metaObject = SystemMetaObject.forObject(person);
String name = (String) metaObject.getValue("name");
metaObject.setValue("name", "tom");
System.out.println("The name is " + name);
// 返回结果是 The name is Tom
}
}
复制代码
代码很直观, 不用作太多解释, 现在的问题是:
SystemMetaObject.forObject
里面做了什么?MetaObject
是怎么进行操作呢?
SystemMetaObject
public final class SystemMetaObject {
public static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
public static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
public static final MetaObject NULL_META_OBJECT = MetaObject.forObject(NullObject.class, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
private SystemMetaObject() {
// Prevent Instantiation of Static Class
}
private static class NullObject {
}
public static MetaObject forObject(Object object) {
return MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
}
}
复制代码
可以看出 SystemMetaObject是一个工厂, 它是只负责 MetaObject 的默认方式创造, 封装了它的构造方法, 可以看出创造 MetaObject 需要传入四个参数, 分别是要操作的对象, ObjectFactory, ObjectWrapperFactory 和 ReflectorFactory。
ObjectFactory
先看看ObjectFactory的接口:
/**
* MyBatis uses an ObjectFactory to create all needed new Objects.
*
* @author Clinton Begin
*/
public interface ObjectFactory {
/**
* Sets configuration properties.
* @param properties configuration properties
*/
default void setProperties(Properties properties) {
// NOP
}
/**
* Creates a new object with default constructor.
*
* @param <T>
* the generic type
* @param type
* Object type
* @return the t
*/
<T> T create(Class<T> type);
/**
* Creates a new object with the specified constructor and params.
*
* @param <T>
* the generic type
* @param type
* Object type
* @param constructorArgTypes
* Constructor argument types
* @param constructorArgs
* Constructor argument values
* @return the t
*/
<T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);
/**
* Returns true if this object can have a set of other objects.
* It's main purpose is to support non-java.util.Collection objects like Scala collections.
*
* @param <T>
* the generic type
* @param type
* Object type
* @return whether it is a collection or not
* @since 3.1.0
*/
<T> boolean isCollection(Class<T> type);
}
复制代码
这接口定义了它是负责创建对象的, 再去看一下 DefaultObjectFactory 是怎么创建对象的:
public class DefaultObjectFactory implements ObjectFactory, Serializable {
private static final long serialVersionUID = -8855120656740914948L;
@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);
// we know types are assignable
return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
}
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();
} else {
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]));
} else {
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);
}
}
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) { // issue #510 Collections Support
classToCreate = TreeSet.class;
} else if (type == Set.class) {
classToCreate = HashSet.class;
} else {
classToCreate = type;
}
return classToCreate;
}
@Override
public <T> boolean isCollection(Class<T> type) {
return Collection.class.isAssignableFrom(type);
}
}
复制代码
可以得知它的主要构造对象的方法是 public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs)
:
@Override
public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
Class<?> classToCreate = resolveInterface(type);
// we know types are assignable
return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
}
复制代码
resolveInterface
负责处理接口, 把它转成相应的实现类:
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) { // issue #510 Collections Support
classToCreate = TreeSet.class;
} else if (type == Set.class) {
classToCreate = HashSet.class;
} else {
classToCreate = type;
}
return classToCreate;
}
复制代码
instantiateClass
则把类创建, 实现很简单, 先看有没有需要传入构造方法的参数, 没有就表示调用无参构造方法, 如果有就调用相应的构造方法:
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();
} else {
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]));
} else {
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);
}
}
复制代码
这里可以注意一下最后的错误处理, 利用了Optional
来做空值的错误处理。
ObjectWrapperFactory
SystemMetaObject
创造的 MetaObject
是没有包装类的。
ReflectorFactory
public interface ReflectorFactory {
boolean isClassCacheEnabled();
void setClassCacheEnabled(boolean classCacheEnabled);
Reflector findForClass(Class<?> type);
}
复制代码
看接口定义, 可以推测两件事, 一是里面会用到缓存, 二是利用 findForClass
找到反射器, 看一下 DefaultReflectorFactory
:
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) {
// synchronized (type) removed see issue #461
return reflectorMap.computeIfAbsent(type, Reflector::new);
} else {
return new Reflector(type);
}
}
}
复制代码
里面内容不多, 由于 classCacheEnabled
为true, 所以一定会调 reflectMap
把反射器 Reflector
存起来 , 重点是要关注 Reflector
, 可以猜出它的 Mybatis 做反射处理的主角:
/**
* This class represents a cached set of class definition information that
* allows for easy mapping between property names and getter/setter methods.
*
* @author Clinton Begin
*/
public class Reflector {
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 Map<String, String> caseInsensitivePropertyMap = new HashMap<>();
public Reflector(Class<?> clazz) {
type = clazz;
addDefaultConstructor(clazz);
addGetMethods(clazz);
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);
}
}
}
复制代码
源码太多我不全部放上来, 详细读者可以自己看, 我只放上构造方法相关的源码, 已经足够说明它是干什么的, 简介已经说明它是做属性名和getter/setter方法的映射。
addDefaultConstructor
会去找类的构造方法, 如果没有参数的则添加到赋值给 defaultConstructor
, addGetMethods
和addSetMethods
类似, 根据方法名称判断是否为getter/setter, 与此同时, 也做相应的特殊处理。
为什么要用 reflectorMap
? 这样就可以复用之前创建的Reflector
? 为什么要用ConcurrentHashMap
? 因为服务器一般是多綫程环境, 用ConcurrentHashMap
可以确保获取和创建都是原子性操作。
MetaObject
终于要讲到今天的主角 MetaObject, 先看源码:
public class MetaObject {
private final Object originalObject;
private final ObjectWrapper objectWrapper;
private final ObjectFactory objectFactory;
private final ObjectWrapperFactory objectWrapperFactory;
private final ReflectorFactory reflectorFactory;
private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
this.originalObject = object;
this.objectFactory = objectFactory;
this.objectWrapperFactory = objectWrapperFactory;
this.reflectorFactory = reflectorFactory;
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);
}
}
public Object getValue(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
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 void setValue(String name, Object value) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
if (value == null) {
// don't instantiate child path if value is null
return;
} else {
metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);
}
}
metaValue.setValue(prop.getChildren(), value);
} else {
objectWrapper.set(prop, value);
}
}
public MetaObject metaObjectForProperty(String name) {
Object value = getValue(name);
return MetaObject.forObject(value, objectFactory, objectWrapperFactory, reflectorFactory);
}
}
复制代码
首先可以看出它是一个代理类, 只是基于原本的类作了功能加强, 然后可以看到它的方法中大量调用 ObjectWrapper
, 其实 MetaObject
只是作一些前置处理, 真正操作它的是 ObjectWrapper
。先看看 ObjectWrapper
接口:
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);
}
复制代码
private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
this.originalObject = object;
this.objectFactory = objectFactory;
this.objectWrapperFactory = objectWrapperFactory;
this.reflectorFactory = reflectorFactory;
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);
}
}
复制代码
因为我们传入的是 DefaultObjectWrapperFactory
, 所以它最后会调用 BeanWrapper
:
public class BeanWrapper extends BaseWrapper {
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());
}
...
}
复制代码
从ReflectorFactory
传入MetaClass
可以看出, 它是处理反射方法的。
getValue/setValue
因为这里会涉及不同情况, 所以要分情况讲解。
先谈讨最简单的情况, 就是只对基本类 (如 String, Integer)作处理的情况:
基本类情况
我再一次把示例代码贴上:
package com.example.metdobjectanalysis.model;
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
-------
package com.example.metdobjectanalysis;
import com.example.metdobjectanalysis.model.Person;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class MetdObjectAnalysisApplicationTests {
@Test
void contextLoads() {
}
@Test
void getTest() {
Person person = new Person();
MetaObject metaObject = SystemMetaObject.forObject(person);
String name = (String) metaObject.getValue("name");
metaObject.setValue("name", "tom");
System.out.println("The name is " + name);
// 返回结果是 The name is Tom
}
}
复制代码
先看MetaObject
的 setValue
到底做了什么:
public void setValue(String name, Object value) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
if (value == null) {
// don't instantiate child path if value is null
return;
} else {
metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);
}
}
metaValue.setValue(prop.getChildren(), value);
} else {
objectWrapper.set(prop, value);
}
}
复制代码
PropertyTokenizer
是指传入的属性名作解析, 因为传入的属性名可能是集合, 也可能是嵌套类型, 因此要做解析处理。 由于现在的情况是单个属性名, 所以直接走到 objectWrapper.set(prop, value)
, 然后走到 BeanWrapper
的 setBeanProperty
方法:
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);
}
复制代码
看代码可以得知, 就是获取类型的setter, 然后调用。getValue也是同理, 就不看源码了。
集合类情况
先看一下例子:
public class Person {
private String name;
private List<String> friends;
public Person(String name) {
this.name = name;
this.friends = new ArrayList<>(10);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getFriends() {
return friends;
}
public void setFriends(int index, String friend) {
this.friends.set(index, friend);
}
}
复制代码
@Test
void collectionTest() {
Person person = new Person("Mary");
person.getFriends().add("Johnson");
MetaObject metaObject = SystemMetaObject.forObject(person);
metaObject.setValue("friends[0]", "Peter");
String friendName = (String) metaObject.getValue("friends[0]");
System.out.println("The friend's name is " + friendName);
// 结果是 The friend's name is Peter
}
复制代码
如果是集合类, 流程是怎么走呢? 这次就要用到 PropertyTokenizer
:
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.");
}
}
复制代码
看一下构造方法, 如果解析到是集合类, 就把索引提取出来。然后又到了BeanWrapper.setValue
方法:
@Override
public void set(PropertyTokenizer prop, Object value) {
if (prop.getIndex() != null) {
Object collection = resolveCollection(prop, object);
setCollectionValue(prop, collection, value);
} else {
setBeanProperty(prop, object, value);
}
}
复制代码
这次要走prop.getIndex() !== null
的流程:
protected Object resolveCollection(PropertyTokenizer prop, Object object) {
if ("".equals(prop.getName())) {
return object;
} else {
return metaObject.getValue(prop.getName());
}
}
复制代码
先获取集合类, 然后调用setCollectionValue
来赋值:
protected void setCollectionValue(PropertyTokenizer prop, Object collection, Object value) {
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("The '" + prop.getName() + "' property of " + collection + " is not a List or Array.");
}
}
}
复制代码
代码看起来好多, 做的无非是判断到底是什么集合类, 调用相应的方法来赋值。
嵌套类情况
终于要谈讨最複杂的情况, 又看一个例子:
public class Student {
private Person person;
private int id;
public Student(int id, String name) {
this.id = id;
this.person = new Person(name);
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
复制代码
@Test
void nestTest() {
Student student = new Student(11, "Tom");
MetaObject metaObject = SystemMetaObject.forObject(student);
metaObject.setValue("person.name", "Peter");
String name = (String) metaObject.getValue("person.name");
System.out.println("The student name is " + name);
// 结果是 The student name is Peter
}
复制代码
这次PropertyTokenizer
有children
了:
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 getChildren() {
return children;
}
@Override
public boolean hasNext() {
return children != null;
}
@Override
public PropertyTokenizer next() {
return new PropertyTokenizer(children);
}
}
复制代码
PropertyTokenizer
, 把.
前的属性赋值给name
, .
后的属性给children
, 如果对它做遍历操作, 则传入children
, 生成新的 PropertyTokenizer
然后接下来有递归操作, 有点绕, 做好准备哈。
我把setValue
的源码再贴上一次:
public void setValue(String name, Object value) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
if (value == null) {
// don't instantiate child path if value is null
return;
} else {
metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);
}
}
metaValue.setValue(prop.getChildren(), value);
} else {
objectWrapper.set(prop, value);
}
}
复制代码
现在因为有children
, 所以会走prop.hasNext
的流程, 进入MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
public MetaObject metaObjectForProperty(String name) {
Object value = getValue(name);
return MetaObject.forObject(value, objectFactory, objectWrapperFactory, reflectorFactory);
}
复制代码
看到它调用getValue
, 然后再生成一个生的MetaObject对象, 注意除了原对象变了, 其馀三个参数是没有变化。看一看getValue
的源码:
public Object getValue(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
return null;
} else {
return metaValue.getValue(prop.getChildren());
}
} else {
return objectWrapper.get(prop);
}
}
复制代码
与setValue
很类似, 因为这里只传入name
, 把它解析后, 是没有children
, 所以就直接走objectWrapper.get(prop);
。然后就到metaValue.setValue(prop.getChildren(), value);
, 生成的新的MetaObject
再一次调用setValue
, 只是这次传入的是children
, 这意味着它会一直调用, 直接prop
没有children
为止, setValue
方法才会走到objectWrapper.set(prop, value)
。
用person.name
作例子走一次流程就更加明白了。进入setValue
, PropertyTokenizer
作解析, 结果如下图所示:
因为有children
, 所以要走prop.hasNext
流程, 进入metaObjectForProperty
, 传入参数person
去调用getValue
, 最后获取Person
对象, 生成新的MetaObject
对象:
基于新的MetaObject
对象, 再一次调用setValue
, 传入children
, 也就是 name
, 因此是:
因为这次没有children
, 所以直接走objectWrapper.set(prop, value);
, 完成赋值。
整个 MetaObject
的基本操作已经讲解完了, 其他操作基本也差不多。