MetaObject源码解析

MetaObject是个反射工具类它支持以“点.”的方式向下递归反射创建对象,属性赋值以及通过key名获取集合对象。

测试

public void shouldGetAndSetNestedField() {
    // 创建一个普通bean
    RichType rich = new RichType();
    // 将bean包装成MetaObject对象
    MetaObject meta = SystemMetaObject.forObject(rich);
    // 以map的方式
    meta.setValue("richType.richMap[key]", "foo");
    // 以属性的方式
    meta.setValue("richType.richField", "foo");
    // 不用.的方式,只能支持到二级属性
    meta.setValue("richProperty", "foo");
    System.out.println(meta.getValue("richType.richMap[key]"));
    System.out.println(meta.getValue("richType.richField"));
    System.out.println(meta.getValue("richProperty"));
  }
// bean的结构
public class RichType {

  private String richField;

  private String richProperty;

  private Map richMap = new HashMap();
}

 

forObject,简单来说就是包装一个对象赋予一些能力

private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory) {
    this.originalObject = object;// 源对象
    this.objectFactory = objectFactory;// 对象工厂
    this.objectWrapperFactory = objectWrapperFactory;// 对象包装器工厂
    // 对象包装器
    if (object instanceof ObjectWrapper) {
        //如果对象本身已经是ObjectWrapper型,则直接赋给objectWrapper
      this.objectWrapper = (ObjectWrapper) object;
    } else if (objectWrapperFactory.hasWrapperFor(object)) {
        //如果有包装器,调用ObjectWrapperFactory.getWrapperFor
      this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
    } else if (object instanceof Map) {
        //如果是Map型,返回MapWrapper
      this.objectWrapper = new MapWrapper(this, (Map) object);
    } else if (object instanceof Collection) {
        //如果是Collection型,返回CollectionWrapper
      this.objectWrapper = new CollectionWrapper(this, (Collection) object);
    } else {
        //除此以外,返回BeanWrapper
      this.objectWrapper = new BeanWrapper(this, object);
    }
  }

分词器源码,主要是将我们的传入的值进行分割

public class PropertyTokenizer implements Iterable<PropertyTokenizer>, Iterator<PropertyTokenizer> {
  // 例子:richType.richMap[key]
  // 当前字段名
  private String name; //richType
  private String indexedName; //richType
  // 下标,如果有值说明子属性有集合类型的
  private String index; //0
  // .后面的字段
  private String children; //richMap

  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);
    }
  }

 setValue,递归调用,思路是先创建上层对象再创建下层属性(对象),知道最上层的对象才能知道它拥有什么属性

public void setValue(String name, Object value) {
    // 分词器进行分词,如richType.richMap[key],返回richType,子属性为richMap[key]
    PropertyTokenizer prop = new PropertyTokenizer(name);
    // 是否有子属性
    if (prop.hasNext()) {
       // 内部就是递归调用,并将调用获取的值进行包装成MetaObject对象
      // 此时传入的richType后面没有.就是直接创建这个对象了。
      MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
      if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
        if (value == null && prop.getChildren() != null) {
          // don't instantiate child path if value is null
          //如果上层就是null了,还得看有没有儿子,没有那就结束
          return;
        } else {
            //否则还得new一个,委派给ObjectWrapper.instantiatePropertyValue创建新实例
          metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);
        }
      }
      //递归调用setValue,给子属性赋值
      metaValue.setValue(prop.getChildren()/*子属性名称*/, value);
    } else {
      //到了最后一层了,所以委派给ObjectWrapper.set,调用setter方法
      objectWrapper.set(prop, value);
    }
  }

metaObjectForProperty 没什么好说的,就是将当前对象包装成MetaObject,如果返回null说明是类不是属性就会进入上面的第5行代码里面的逻辑

public MetaObject metaObjectForProperty(String name) {
    //实际是递归调用
  Object value = getValue(name);
  return MetaObject.forObject(value, objectFactory, objectWrapperFactory);
}

getValue套路跟setValue一样的,获取prop.name字段的对象

public Object getValue(String name) {
  PropertyTokenizer prop = new PropertyTokenizer(name);
  if (prop.hasNext()) {
    MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
    if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
        //如果上层就是null了,那就结束,返回null
      return null;
    } else {
        //否则继续看下一层,递归调用getValue
     return metaValue.getValue(prop.getChildren());
    }
  } else {
    return objectWrapper.get(prop);
  }
}

objectWrapper.get(prop, value)(objectWrapper.set(prop, value)); 两个作用,解析集合并赋值返回,反射调用对象的getter方法

@Override
public Object get(PropertyTokenizer prop) {
    //如果有index(有中括号),说明是集合,那就要解析集合
  if (prop.getIndex() != null) {
    // 内部还是递归调用getValue,主要是通过反射获取并创建集合属性对象,到最终都会走向getBeanProperty方法
    Object collection = resolveCollection(prop, object);
    // 给集合赋值并获取
    return getCollectionValue(prop, collection);
  } else {
      //否则,getBeanProperty,底层通过反射调用getter方法
    return getBeanProperty(prop, object);
  }
}
// 如上
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);
    }
  }

 集合赋值方法

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.");
    }
  }
}

整体流程图

总结:通过分词区分当前属性和子属性,通过反射先创建当前属性,后创建子属性,反复循环操作。

 

posted @ 2022-05-31 19:19  猫长寿  阅读(253)  评论(0编辑  收藏  举报