MetaObject mybatis反射体系

概述

MetaObject mybatis反射体系_第1张图片
MetaObject是Mybatis一个反射工具类,进行了高度封装,根据属性进行获取值,设置值,支持对象的嵌套这种结构
objectWrapper 是获取当前对象的属性值,不支持对象的嵌套
MetaClass 支持子属性的获取
Reflector 就是直接使用反射获取值,或者设置值,相当于一层一层的进行封装上来的,我们从上而下进行看

MetaObject

虽然我们今天是主要看MetaOject但是只看这一个类就没啥看头了,和ObjectWrapper 结合起来一起看

 //原始对象
  private final Object originalObject;
  //包装对象
  private final ObjectWrapper objectWrapper;
  private final ObjectFactory objectFactory;
  private final ObjectWrapperFactory objectWrapperFactory;
  private final ReflectorFactory reflectorFactory;

几个属性 我们主要关心 objectWrapper,其他的几个工厂类全部默认的就可以,代码基本没有啥也;

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)) {  //默认是返回fase 除非我们自己定义 objectWrapperFactory
      this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
    } else if (object instanceof Map) {  // 原始类属于map
      this.objectWrapper = new MapWrapper(this, (Map) object);
    } else if (object instanceof Collection) { // 原始类属于集合
      this.objectWrapper = new CollectionWrapper(this, (Collection) object);
    } else {  //普通的bean对象
      this.objectWrapper = new BeanWrapper(this, object);
    }
  }

构造方法私有化

public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
    if (object == null) {
      return SystemMetaObject.NULL_META_OBJECT;
    } else {
      return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
    }
  }

通过这个forObject获取MetaObject对象,如果传入的原始对象是null,则返回一个SystemMetaObject

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

最核心的两个方法,后面一起将流程

MetaObject 运行逻辑

这是老师讲课使用的一个例子

MetaObject mybatis反射体系_第2张图片

自己写了一个例子:ps:这种问题自己多进行debug感觉比看这种图有用:
MetaObject mybatis反射体系_第3张图片

MetaObject mybatis反射体系_第4张图片

public static void main(String[] args) {
    Address address = new Address();
    address.setTon("address1");
    Address address2 = new Address();
    address2.setTon("address2");

    Student stu = new Student();
    stu.setAddress(address);
    stu.setName("张三");
    stu.setAge(12);

    Student stu2 = new Student();
    stu2.setAddress(address2);
    stu2.setName("张三");
    stu2.setAge(12);

    ClassRoom classRoom = new ClassRoom();
    classRoom.setNo(1);
    ArrayList students = new ArrayList<>();
    students.add(stu);
    students.add(stu2);
    classRoom.setStudentList(students);
    Map tags = new HashMap<>();
    tags.put("一班","优秀班级");
    classRoom.setTags(tags);

    MetaObject metaObject = MetaObject.forObject(classRoom, new DefaultObjectFactory(), new DefaultObjectWrapperFactory(), new DefaultReflectorFactory());

    Object value = metaObject.getValue("no");
    System.out.println(value);

    Object value1 = metaObject.getValue("studentList[0].address.ton");
    System.out.println(value1);

    Object tags1 = metaObject.getValue("tags");
    System.out.println(tags1);

  }

Object value1 = metaObject.getValue(“studentList[0].address.ton”);
我们拿这个来描述其中运行的逻辑吧:

  1. studentList[0].address.ton 这个获取值,是否有子属性
  2. 有,根据studentList[0]进行获取集合中的第一个元素值(stu)转成MetaObject,进而再获取子元素,address.ton
  3. 进行递归调用 address.ton获取值,进2进行判断,直到ton没有子元素
  4. objectWrapper.get(prop);进行获取,再往下就是反射获取了

ps:
studentList[0] 这个获取第一个元素值的时候,首先利用name获取到该属性的集合,再利用indexedName,获取第几个元素,这样就可以直接获取到集合中第几个元素的值

public class PropertyTokenizer implements Iterator {
  //属性名称
  private String name;
  //属性名称➕索引 主要是集合属性 eg: user[0]
  private final String indexedName;

本来想着搞一个比较完整的流程,太复杂了,还比较乱,这才一半不到,算了自己debug吧
MetaObject mybatis反射体系_第5张图片

你可能感兴趣的:(#,mybatis,java,单元测试,html,MetaObject)