mybatis metaObject 详解

1.metaObject 是啥

MetaObject类相当于一个对象工具类,Mybatis在sql参数设置和结果集映射里经常使用到这个对象。 映射是指结果集中的列填充至JAVA Bean属性。这就必须用到反射,而Bean的属性 多种多样的有普通属性、对象、集合、Map都有可能。为了更加方便的操作Bean的属性,MyBatis提供了MeataObject 工具类,其简化了对象属性的操作。

1.1 metaObject的使用

      实体类

import lombok.Data;

@Data
public class user {
    /**
     * 名称
     */
    private String name;

    /**
     * id
     */
    private String id;
}

 测试

public static void main(String[] args)  {
    
     //装饰器模式
    user bizDict = new user();
     Configuration configuration=new Configuration();
     // 装饰
    MetaObject metaobject = configuration.newMetaObject(bizDict);
    metaobject.setValue("name","babababa");
        System.out.println(metaobject.getValue(  "name"));
}

输出

2.mybatis对metaObject 详解

2.1 全景图

2.2 mybatis 的metaObject类详细解说

/*
 *    Copyright 2009-2023 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       https://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.reflection;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.property.PropertyTokenizer;
import org.apache.ibatis.reflection.wrapper.BeanWrapper;
import org.apache.ibatis.reflection.wrapper.CollectionWrapper;
import org.apache.ibatis.reflection.wrapper.MapWrapper;
import org.apache.ibatis.reflection.wrapper.ObjectWrapper;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;

/**
 * @author Clinton Begin
 */
public class MetaObject {

  // 原始的 Java 对象
  private final Object originalObject;

  // 对象包装器,用于获取和设置对象的属性值
  private final ObjectWrapper objectWrapper;

  // 对象工厂,用于创建 Java 对象
  private final ObjectFactory objectFactory;

  // 对象包装器工厂,用于创建对象包装器
  private final ObjectWrapperFactory objectWrapperFactory;

  // 反射器工厂,用于创建反射器
  private final ReflectorFactory reflectorFactory;

  // 构造函数,创建 MetaObject 对象
  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);
    }
  }

  // 静态工厂方法,用于创建 MetaObject 对象
  public static MetaObject forObject(Object object, ObjectFactory objectFactory,
                                     ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
    if (object == null) {
      return SystemMetaObject.NULL_META_OBJECT;
    }
    return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
  }

  // 获取对象工厂
  public ObjectFactory getObjectFactory() {
    return objectFactory;
  }

  // 获取对象包装器工厂
  public ObjectWrapperFactory getObjectWrapperFactory() {
    return objectWrapperFactory;
  }

  // 获取反射器工厂
  public ReflectorFactory getReflectorFactory() {
    return reflectorFactory;
  }

  // 获取原始 Java 对象
  public Object getOriginalObject() {
    return originalObject;
  }

  // 查找属性名,支持驼峰命名和下划线命名的转换
  public String findProperty(String propName, boolean useCamelCaseMapping) {
    return objectWrapper.findProperty(propName, useCamelCaseMapping);
  }

  // 获取所有 getter 方法名
  public String[] getGetterNames() {
    return objectWrapper.getGetterNames();
  }

  // 获取所有 setter 方法名
  public String[] getSetterNames() {
    return objectWrapper.getSetterNames();
  }

 
  /**
   * 获取指定属性的 setter 方法的参数类型
   * @param name
   * @return
   */
  public Class<?> getSetterType(String name) {
    return objectWrapper.getSetterType(name);
  }

 
  /**
   * 获取指定属性的 getter 方法的返回值类型
   * @param name
   * @return
   */
  public Class<?> getGetterType(String name) {
    return objectWrapper.getGetterType(name);
  }

  
  /**
   * 判断指定属性是否有 setter 方法
   * @param name
   * @return
   */
  public boolean hasSetter(String name) {
    return objectWrapper.hasSetter(name);
  }

 

  /**
   * 判断指定属性是否有 getter 方法
   * @param name
   * @return
   */
  public boolean hasGetter(String name) {
    return objectWrapper.hasGetter(name);
  }



  /**
   * 获取指定属性的值
   * @param name
   * @return
   */
  public Object getValue(String name) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (!prop.hasNext()) {
      return objectWrapper.get(prop);
    }
    MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());
    if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
      return null;
    } else {
      return metaValue.getValue(prop.getChildren());
    }
  }

  

  /**
   * 设置指定属性的值
   * @param name
   * @param value
   */
  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) {
          // 如果值为 null,则不创建子路径
          return;
        }
        metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);
      }
      metaValue.setValue(prop.getChildren(), value);
    } else {
      objectWrapper.set(prop, value);
    }
  }

 

  /**
   * 获取指定属性的 MetaObject 对象
   * @param name
   * @return
   */
  public MetaObject metaObjectForProperty(String name) {
    Object value = getValue(name);
    return MetaObject.forObject(value, objectFactory, objectWrapperFactory, reflectorFactory);
  }

 

  /**
   * 判断对象是否为集合类型
   * @return
   */
  public boolean isCollection() {
    return objectWrapper.isCollection();
  }

  

  /**
   * 向集合类型对象中添加元素
   * @param element
   */
  public void add(Object element) {
    objectWrapper.add(element);
  }

 

  /**
   * 向集合类型对象中添加多个元素
   * @param list
   * @param <E>
   */
  public <E> void addAll(List<E> list) {
    objectWrapper.addAll(list);
  }

}

2.3  BeanWrapper 代码详细解析

/*
 *    Copyright 2009-2023 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       https://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.reflection.wrapper;

import java.util.List;

import org.apache.ibatis.reflection.ExceptionUtil;
import org.apache.ibatis.reflection.MetaClass;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.ReflectionException;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.invoker.Invoker;
import org.apache.ibatis.reflection.property.PropertyTokenizer;

/**
 * @author Clinton Begin
 */
/**
 * BeanWrapper MyBatis 中的一个包装类,用于实现对 JavaBean 对象的包装和操作。
 * 主要实现了以下功能:
 * 1. 获取 JavaBean 对象的属性值,包括普通属性和集合属性。
 * 2. 设置 JavaBean 对象的属性值,包括普通属性和集合属性。
 * 3. 查找 JavaBean 对象的属性名。
 * 4. 获取 JavaBean 对象的 getter 方法名和 setter 方法名。
 * 5. 获取 JavaBean 对象的 getter 方法返回值类型和 setter 方法参数类型。
 * 6. 判断 JavaBean 对象是否有指定属性的 getter 方法和 setter 方法。
 * 7. 实例化 JavaBean 对象的属性值。
 * 8. 判断 JavaBean 对象是否为集合类型。
 * 9. JavaBean 对象的集合属性中添加元素。
 */
public class BeanWrapper extends BaseWrapper {
  /**
   * 被包装的 JavaBean 对象
   */
  private final Object object;
  /**
   *  JavaBean 对象的元信息类
   */
  private final MetaClass metaClass;

  /**
   *  构造方法,接收 MetaObject 对象和 JavaBean 对象
   * @param metaObject
   * @param object
   */
  public BeanWrapper(MetaObject metaObject, Object object) {
    // 调用父类构造方法
    super(metaObject);
    // 初始化被包装的 JavaBean 对象
    this.object = object;
    // 初始化 JavaBean 对象的元信息类
    this.metaClass = MetaClass.forClass(object.getClass(), metaObject.getReflectorFactory());
  }

  /**
   * 获取 JavaBean 对象的属性值
   * @param prop
   * @return
   */
  @Override
  public Object get(PropertyTokenizer prop) {
    // 如果属性是集合类型
    if (prop.getIndex() != null) {
      // 解析集合类型属性
      Object collection = resolveCollection(prop, object);
      // 获取集合类型属性的值
      return getCollectionValue(prop, collection);
    }
    // 获取普通属性的值
    return getBeanProperty(prop, object);
  }

  /**
   *  // 设置 JavaBean 对象的属性值
   * @param prop
   * @param value
   */
  @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);
    }
  }

  /**
   *  查找 JavaBean 对象的属性名
   * @param name
   * @param useCamelCaseMapping
   * @return
   */
  @Override
  public String findProperty(String name, boolean useCamelCaseMapping) {
    // 调用元信息类的方法查找属性名
    return metaClass.findProperty(name, useCamelCaseMapping);
  }

  /**
   * 获取 JavaBean 对象的 getter 方法名
   * @return
   */
  @Override
  public String[] getGetterNames() {
    // 调用元信息类的方法获取 getter 方法名
    return metaClass.getGetterNames();
  }

  /**
   * 获取 JavaBean 对象的 setter 方法名
   * @return
   */
  @Override
  public String[] getSetterNames() {
    // 调用元信息类的方法获取 setter 方法名
    return metaClass.getSetterNames();
  }

  /**
   * 获取 JavaBean 对象的 setter 方法参数类型
   * @param name
   * @return
   */
  @Override
  public Class<?> getSetterType(String name) {
    // 解析属性名
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (!prop.hasNext()) {
      // 如果没有子属性,直接调用元信息类的方法获取参数类型
      return metaClass.getSetterType(name);
    }
    // 获取子属性的元对象
    MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
    // 如果子属性为空
    if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
      // 直接调用元信息类的方法获取参数类型
      return metaClass.getSetterType(name);
    } else {
      // 递归获取子属性的参数类型
      return metaValue.getSetterType(prop.getChildren());
    }
  }

  /**
   * 获取 JavaBean 对象的 getter 方法返回值类型
   * @param name
   * @return
   */
  @Override
  public Class<?> getGetterType(String name) {
    // 解析属性名
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (!prop.hasNext()) {
      // 如果没有子属性,直接调用元信息类的方法获取返回值类型
      return metaClass.getGetterType(name);
    }
    // 获取子属性的元对象
    MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
    // 如果子属性为空
    if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
      // 直接调用元信息类的方法获取返回值类型
      return metaClass.getGetterType(name);
    } else {
      // 递归获取子属性的返回值类型
      return metaValue.getGetterType(prop.getChildren());
    }
  }

  /**
   *  判断 JavaBean 对象是否有指定属性的 setter 方法
   * @param name
   * @return
   */
  @Override
  public boolean hasSetter(String name) {
    // 解析属性名
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (!prop.hasNext()) {
      // 如果没有子属性,直接调用元信息类的方法判断是否有 setter 方法
      return metaClass.hasSetter(name);
    }
    // 如果有 setter 方法
    if (metaClass.hasSetter(prop.getIndexedName())) {
      // 获取子属性的元对象
      MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
      // 如果子属性为空
      if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
        // 直接调用元信息类的方法判断是否有 setter 方法
        return metaClass.hasSetter(name);
      } else {
        // 递归判断子属性是否有 setter 方法
        return metaValue.hasSetter(prop.getChildren());
      }
    } else {
      // 如果没有 setter 方法,返回 false
      return false;
    }
  }

  /**
   * 判断 JavaBean 对象是否有指定属性的 getter 方法
   * @param name
   * @return
   */
  @Override
  public boolean hasGetter(String name) {
    // 解析属性名
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (!prop.hasNext()) {
      // 如果没有子属性,直接调用元信息类的方法判断是否有 getter 方法
      return metaClass.hasGetter(name);
    }
    // 如果有 getter 方法
    if (metaClass.hasGetter(prop.getIndexedName())) {
      // 获取子属性的元对象
      MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
      // 如果子属性为空
      if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
        // 直接调用元信息类的方法判断是否有 getter 方法
        return metaClass.hasGetter(name);
      } else {
        // 递归判断子属性是否有 getter 方法
        return metaValue.hasGetter(prop.getChildren());
      }
    } else {
      // 如果没有 getter 方法,返回 false
      return false;
    }
  }

  /**
   * 实例化 JavaBean 对象的属性值
   * @param name
   * @param prop
   * @param objectFactory
   * @return
   */
  @Override
  public MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory) {
    // 子属性的元对象
    MetaObject metaValue;
    // 获取子属性的参数类型
    Class<?> type = getSetterType(prop.getName());
    try {
      // 创建新的对象
      Object newObject = objectFactory.create(type);
      metaValue = MetaObject.forObject(newObject, metaObject.getObjectFactory(), metaObject.getObjectWrapperFactory(),
        // 创建新的元对象
        metaObject.getReflectorFactory());
      // 设置子属性的值
      set(prop, newObject);
    } catch (Exception e) {
      // 抛出 ReflectionException 异常
      throw new ReflectionException("Cannot set value of property '" + name + "' because '" + name
        + "' is null and cannot be instantiated on instance of " + type.getName() + ". Cause:" + e.toString(), e);
    }
    // 返回子属性的元对象
    return metaValue;
  }

  /**
   * 获取 JavaBean 对象的属性值
   * @param prop
   * @param object
   * @return
   */
  private Object getBeanProperty(PropertyTokenizer prop, Object object) {
    try {
      // 获取 getter 方法的 Invoker 对象
      Invoker method = metaClass.getGetInvoker(prop.getName());
      try {
        // 调用 getter 方法获取属性值
        return method.invoke(object, NO_ARGUMENTS);
      } catch (Throwable t) {
        // 抛出异常
        throw ExceptionUtil.unwrapThrowable(t);
      }
    } catch (RuntimeException e) {
      // 抛出异常
      throw e;
    } catch (Throwable t) {
      throw new ReflectionException(
        // 抛出 ReflectionException 异常
        "Could not get property '" + prop.getName() + "' from " + object.getClass() + ". Cause: " + t.toString(), t);
    }
  }

  /**
   * 设置 JavaBean 对象的属性值
   * @param prop
   * @param object
   * @param value
   */
  private void setBeanProperty(PropertyTokenizer prop, Object object, Object value) {
    try {
      // 获取 setter 方法的 Invoker 对象
      Invoker method = metaClass.getSetInvoker(prop.getName());
      // 设置参数数组
      Object[] params = { value };
      try {
        // 调用 setter 方法设置属性值
        method.invoke(object, params);
      } catch (Throwable t) {
        // 抛出异常
        throw ExceptionUtil.unwrapThrowable(t);
      }
    } catch (Throwable t) {
      // 抛出 ReflectionException 异常
      throw new ReflectionException("Could not set property '" + prop.getName() + "' of '" + object.getClass()
        + "' with value '" + value + "' Cause: " + t.toString(), t);
    }
  }

  /**
   *  判断 JavaBean 对象是否为集合类型
   * @return
   */
  @Override
  public boolean isCollection() {
    // 不是集合类型,返回 false
    return false;
  }

  /**
   *  JavaBean 对象的集合属性中添加元素
   * @param element
   */
  @Override
  public void add(Object element) {
    // 抛出 UnsupportedOperationException 异常
    throw new UnsupportedOperationException();
  }

  /**
   * JavaBean 对象的集合属性中添加元素
   * @param list
   * @param <E>
   */
  @Override
  public <E> void addAll(List<E> list) {
    // 抛出 UnsupportedOperationException 异常
    throw new UnsupportedOperationException();
  }
}

2.4 MetaClass 代码详细解说

/*
 *    Copyright 2009-2023 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       https://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.reflection;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;

import org.apache.ibatis.reflection.invoker.GetFieldInvoker;
import org.apache.ibatis.reflection.invoker.Invoker;
import org.apache.ibatis.reflection.invoker.MethodInvoker;
import org.apache.ibatis.reflection.property.PropertyTokenizer;

/**
 * @author Clinton Begin
 */
/**
 * MetaClass 类用于对 Java 类进行反射操作,可以获取类的属性、方法、构造方法等信息。
 * 它是对 Reflector 类的进一步封装,提供了更加方便的 API */
public class MetaClass {

  private final ReflectorFactory reflectorFactory; // Reflector 工厂,用于创建 Reflector 对象
  private final Reflector reflector; // 封装了目标类的反射信息的 Reflector 对象

  private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
    this.reflectorFactory = reflectorFactory;
    this.reflector = reflectorFactory.findForClass(type); // 根据目标类创建 Reflector 对象
  }

  /**
   * 根据目标类和 Reflector 工厂创建 MetaClass 对象
   */
  public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) {
    return new MetaClass(type, reflectorFactory);
  }

  /**
   * 根据属性名获取属性的名称,比如将 "userName" 转换为 "user_name"   * 如果没有找到,则返回 null   */
  public String findProperty(String name) {
    StringBuilder prop = buildProperty(name, new StringBuilder());
    return prop.length() > 0 ? prop.toString() : null;
  }

  /**
   * 根据属性名获取属性的名称,比如将 "userName" 转换为 "user_name"   * 如果没有找到,则返回 null   * useCamelCaseMapping 参数用于指定是否使用驼峰命名法。
   */
  public String findProperty(String name, boolean useCamelCaseMapping) {
    if (useCamelCaseMapping) {
      name = name.replace("_", "");
    }
    return findProperty(name);
  }

  /**
   * 获取所有可读的属性名
   */
  public String[] getGetterNames() {
    return reflector.getGetablePropertyNames();
  }

  /**
   * 获取所有可写的属性名
   */
  public String[] getSetterNames() {
    return reflector.getSetablePropertyNames();
  }

  /**
   * 根据属性名获取 setter 方法的参数类型
   */
  public Class<?> getSetterType(String name) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      MetaClass metaProp = metaClassForProperty(prop.getName());
      return metaProp.getSetterType(prop.getChildren());
    }
    return reflector.getSetterType(prop.getName());
  }

  /**
   * 根据属性名获取 getter 方法的返回类型
   */
  public Class<?> getGetterType(String name) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      MetaClass metaProp = metaClassForProperty(prop);
      return metaProp.getGetterType(prop.getChildren());
    }
    // issue #506. Resolve the type inside a Collection Object
    return getGetterType(prop);
  }

  /**
   * 根据属性名获取 getter 方法的返回类型
   * 这个方法主要用于解析集合类型的泛型参数类型
   */
  private Class<?> getGetterType(PropertyTokenizer prop) {
    Class<?> type = reflector.getGetterType(prop.getName());
    if (prop.getIndex() != null && Collection.class.isAssignableFrom(type)) {
      Type returnType = getGenericGetterType(prop.getName());
      if (returnType instanceof ParameterizedType) {
        Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments();
        if (actualTypeArguments != null && actualTypeArguments.length == 1) {
          returnType = actualTypeArguments[0];
          if (returnType instanceof Class) {
            type = (Class<?>) returnType;
          } else if (returnType instanceof ParameterizedType) {
            type = (Class<?>) ((ParameterizedType) returnType).getRawType();
          }
        }
      }
    }
    return type;
  }

  /**
   * 获取 getter 方法的返回类型的泛型参数类型
   */
  private Type getGenericGetterType(String propertyName) {
    try {
      Invoker invoker = reflector.getGetInvoker(propertyName);
      if (invoker instanceof MethodInvoker) {
        Field declaredMethod = MethodInvoker.class.getDeclaredField("method");
        declaredMethod.setAccessible(true);
        Method method = (Method) declaredMethod.get(invoker);
        return TypeParameterResolver.resolveReturnType(method, reflector.getType());
      }
      if (invoker instanceof GetFieldInvoker) {
        Field declaredField = GetFieldInvoker.class.getDeclaredField("field");
        declaredField.setAccessible(true);
        Field field = (Field) declaredField.get(invoker);
        return TypeParameterResolver.resolveFieldType(field, reflector.getType());
      }
    } catch (NoSuchFieldException | IllegalAccessException e) {
      // Ignored
    }
    return null;
  }

  /**
   * 判断是否存在指定属性的 setter 方法
   */
  public boolean hasSetter(String name) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (!prop.hasNext()) {
      return reflector.hasSetter(prop.getName());
    }
    if (reflector.hasSetter(prop.getName())) {
      MetaClass metaProp = metaClassForProperty(prop.getName());
      return metaProp.hasSetter(prop.getChildren());
    } else {
      return false;
    }
  }

  /**
   * 判断是否存在指定属性的 getter 方法
   */
  public boolean hasGetter(String name) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (!prop.hasNext()) {
      return reflector.hasGetter(prop.getName());
    }
    if (reflector.hasGetter(prop.getName())) {
      MetaClass metaProp = metaClassForProperty(prop);
      return metaProp.hasGetter(prop.getChildren());
    } else {
      return false;
    }
  }

  /**
   * 获取指定属性的 getter 方法对应的 Invoker 对象
   */
  public Invoker getGetInvoker(String name) {
    return reflector.getGetInvoker(name);
  }

  /**
   * 获取指定属性的 setter 方法对应的 Invoker 对象
   */
  public Invoker getSetInvoker(String name) {
    return reflector.getSetInvoker(name);
  }

  /**
   * 递归构建属性的名称,比如将 "user.name" 转换为 "user_name"   */
  private StringBuilder buildProperty(String name, StringBuilder builder) {
    PropertyTokenizer prop = new PropertyTokenizer(name);
    if (prop.hasNext()) {
      String propertyName = reflector.findPropertyName(prop.getName());
      if (propertyName != null) {
        builder.append(propertyName);
        builder.append(".");
        MetaClass metaProp = metaClassForProperty(propertyName);
        metaProp.buildProperty(prop.getChildren(), builder);
      }
    } else {
      String propertyName = reflector.findPropertyName(name);
      if (propertyName != null) {
        builder.append(propertyName);
      }
    }
    return builder;
  }

  /**
   * 判断目标类是否有默认构造方法
   */
  public boolean hasDefaultConstructor() {
    return reflector.hasDefaultConstructor();
  }

  /**
   * 根据属性名创建 MetaClass 对象
   */
  public MetaClass metaClassForProperty(String name) {
    Class<?> propType = reflector.getGetterType(name);
    return MetaClass.forClass(propType, reflectorFactory);
  }

  /**
   * 根据属性名创建 MetaClass 对象
   */
  private MetaClass metaClassForProperty(PropertyTokenizer prop) {
    Class<?> propType = getGetterType(prop);
    return MetaClass.forClass(propType, reflectorFactory);
  }

}

2.5 测试

/*
 *    Copyright 2009-2023 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       https://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.domain.misc;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class RichType {

  private RichType richType;

  private String richField;

  private String richProperty;

  private Map richMap = new HashMap<>();

  private List richList = new ArrayList<>() {
    private static final long serialVersionUID = 1L;
    {
      add("bar");
    }
  };

  public RichType getRichType() {
    return richType;
  }

  public void setRichType(RichType richType) {
    this.richType = richType;
  }

  public String getRichProperty() {
    return richProperty;
  }

  public void setRichProperty(String richProperty) {
    this.richProperty = richProperty;
  }

  public List getRichList() {
    return richList;
  }

  public void setRichList(List richList) {
    this.richList = richList;
  }

  public Map getRichMap() {
    return richMap;
  }

  public void setRichMap(Map richMap) {
    this.richMap = richMap;
  }
}

测试用例

/*
 *    Copyright 2009-2023 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       https://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.reflection;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.domain.blog.Author;
import org.apache.ibatis.domain.blog.Section;
import org.apache.ibatis.domain.misc.CustomBeanWrapper;
import org.apache.ibatis.domain.misc.CustomBeanWrapperFactory;
import org.apache.ibatis.domain.misc.RichType;
import org.junit.jupiter.api.Test;

class MetaObjectTest {

  @Test
  void shouldGetAndSetField() {
    RichType rich = new RichType();
    MetaObject meta = SystemMetaObject.forObject(rich);
    meta.setValue("richField", "foo");
    assertEquals("foo", meta.getValue("richField"));
  }

  @Test
  void shouldGetAndSetNestedField() {
    RichType rich = new RichType();
    MetaObject meta = SystemMetaObject.forObject(rich);
    meta.setValue("richType.richField", "foo");
    assertEquals("foo", meta.getValue("richType.richField"));
  }

  @Test
  void shouldGetAndSetProperty() {
    RichType rich = new RichType();
    MetaObject meta = SystemMetaObject.forObject(rich);
    meta.setValue("richProperty", "foo");
    assertEquals("foo", meta.getValue("richProperty"));
  }

  @Test
  void shouldGetAndSetNestedProperty() {
    RichType rich = new RichType();
    MetaObject meta = SystemMetaObject.forObject(rich);
    meta.setValue("richType.richProperty", "foo");
    assertEquals("foo", meta.getValue("richType.richProperty"));
  }

  @Test
  void shouldGetAndSetMapPair() {
    RichType rich = new RichType();
    MetaObject meta = SystemMetaObject.forObject(rich);
    meta.setValue("richMap.key", "foo");
    assertEquals("foo", meta.getValue("richMap.key"));
  }

  @Test
  void shouldGetAndSetMapPairUsingArraySyntax() {
    RichType rich = new RichType();
    MetaObject meta = SystemMetaObject.forObject(rich);
    meta.setValue("richMap[key]", "foo");
    assertEquals("foo", meta.getValue("richMap[key]"));
  }

  @Test
  void shouldGetAndSetNestedMapPair() {
    RichType rich = new RichType();
    MetaObject meta = SystemMetaObject.forObject(rich);
    meta.setValue("richType.richMap.key", "foo");
    assertEquals("foo", meta.getValue("richType.richMap.key"));
  }

  @Test
  void shouldGetAndSetNestedMapPairUsingArraySyntax() {
    RichType rich = new RichType();
    MetaObject meta = SystemMetaObject.forObject(rich);
    meta.setValue("richType.richMap[key]", "foo");
    assertEquals("foo", meta.getValue("richType.richMap[key]"));
  }

  @Test
  void shouldGetAndSetListItem() {
    RichType rich = new RichType();
    MetaObject meta = SystemMetaObject.forObject(rich);
    meta.setValue("richList[0]", "foo");
    assertEquals("foo", meta.getValue("richList[0]"));
  }

  @Test
  void shouldGetAndSetNestedListItem() {
    RichType rich = new RichType();
    MetaObject meta = SystemMetaObject.forObject(rich);
    meta.setValue("richType.richList[0]", "foo");
    assertEquals("foo", meta.getValue("richType.richList[0]"));
  }

  @Test
  void shouldGetReadablePropertyNames() {
    RichType rich = new RichType();
    MetaObject meta = SystemMetaObject.forObject(rich);
    String[] readables = meta.getGetterNames();
    assertEquals(5, readables.length);
    for (String readable : readables) {
      assertTrue(meta.hasGetter(readable));
      assertTrue(meta.hasGetter("richType." + readable));
    }
    assertTrue(meta.hasGetter("richType"));
  }

  @Test
  void shouldGetWriteablePropertyNames() {
    RichType rich = new RichType();
    MetaObject meta = SystemMetaObject.forObject(rich);
    String[] writeables = meta.getSetterNames();
    assertEquals(5, writeables.length);
    for (String writeable : writeables) {
      assertTrue(meta.hasSetter(writeable));
      assertTrue(meta.hasSetter("richType." + writeable));
    }
    assertTrue(meta.hasSetter("richType"));
  }

  @Test
  void shouldSetPropertyOfNullNestedProperty() {
    MetaObject richWithNull = SystemMetaObject.forObject(new RichType());
    richWithNull.setValue("richType.richProperty", "foo");
    assertEquals("foo", richWithNull.getValue("richType.richProperty"));
  }

  @Test
  void shouldSetPropertyOfNullNestedPropertyWithNull() {
    MetaObject richWithNull = SystemMetaObject.forObject(new RichType());
    richWithNull.setValue("richType.richProperty", null);
    assertNull(richWithNull.getValue("richType.richProperty"));
  }

  @Test
  void shouldGetPropertyOfNullNestedProperty() {
    MetaObject richWithNull = SystemMetaObject.forObject(new RichType());
    assertNull(richWithNull.getValue("richType.richProperty"));
  }

  @Test
  void shouldVerifyHasReadablePropertiesReturnedByGetReadablePropertyNames() {
    MetaObject object = SystemMetaObject.forObject(new Author());
    for (String readable : object.getGetterNames()) {
      assertTrue(object.hasGetter(readable));
    }
  }

  @Test
  void shouldVerifyHasWriteablePropertiesReturnedByGetWriteablePropertyNames() {
    MetaObject object = SystemMetaObject.forObject(new Author());
    for (String writeable : object.getSetterNames()) {
      assertTrue(object.hasSetter(writeable));
    }
  }

  @Test
  void shouldSetAndGetProperties() {
    MetaObject object = SystemMetaObject.forObject(new Author());
    object.setValue("email", "test");
    assertEquals("test", object.getValue("email"));

  }

  @Test
  void shouldVerifyPropertyTypes() {
    MetaObject object = SystemMetaObject.forObject(new Author());
    assertEquals(6, object.getSetterNames().length);
    assertEquals(int.class, object.getGetterType("id"));
    assertEquals(String.class, object.getGetterType("username"));
    assertEquals(String.class, object.getGetterType("password"));
    assertEquals(String.class, object.getGetterType("email"));
    assertEquals(String.class, object.getGetterType("bio"));
    assertEquals(Section.class, object.getGetterType("favouriteSection"));
  }

  @Test
  void shouldDemonstrateDeeplyNestedMapProperties() {
    HashMap<String, String> map = new HashMap<>();
    MetaObject metaMap = SystemMetaObject.forObject(map);

    assertTrue(metaMap.hasSetter("id"));
    assertTrue(metaMap.hasSetter("name.first"));
    assertTrue(metaMap.hasSetter("address.street"));

    assertFalse(metaMap.hasGetter("id"));
    assertFalse(metaMap.hasGetter("name.first"));
    assertFalse(metaMap.hasGetter("address.street"));

    metaMap.setValue("id", "100");
    metaMap.setValue("name.first", "Clinton");
    metaMap.setValue("name.last", "Begin");
    metaMap.setValue("address.street", "1 Some Street");
    metaMap.setValue("address.city", "This City");
    metaMap.setValue("address.province", "A Province");
    metaMap.setValue("address.postal_code", "1A3 4B6");

    assertTrue(metaMap.hasGetter("id"));
    assertTrue(metaMap.hasGetter("name.first"));
    assertTrue(metaMap.hasGetter("address.street"));

    assertEquals(3, metaMap.getGetterNames().length);
    assertEquals(3, metaMap.getSetterNames().length);

    @SuppressWarnings("unchecked")
    Map<String, String> name = (Map<String, String>) metaMap.getValue("name");
    @SuppressWarnings("unchecked")
    Map<String, String> address = (Map<String, String>) metaMap.getValue("address");

    assertEquals("Clinton", name.get("first"));
    assertEquals("1 Some Street", address.get("street"));
  }

  @Test
  void shouldDemonstrateNullValueInMap() {
    HashMap<String, String> map = new HashMap<>();
    MetaObject metaMap = SystemMetaObject.forObject(map);
    assertFalse(metaMap.hasGetter("phone.home"));

    metaMap.setValue("phone", null);
    assertTrue(metaMap.hasGetter("phone"));
    // hasGetter returns true if the parent exists and is null.
    assertTrue(metaMap.hasGetter("phone.home"));
    assertTrue(metaMap.hasGetter("phone.home.ext"));
    assertNull(metaMap.getValue("phone"));
    assertNull(metaMap.getValue("phone.home"));
    assertNull(metaMap.getValue("phone.home.ext"));

    metaMap.setValue("phone.office", "789");
    assertFalse(metaMap.hasGetter("phone.home"));
    assertFalse(metaMap.hasGetter("phone.home.ext"));
    assertEquals("789", metaMap.getValue("phone.office"));
    assertNotNull(metaMap.getValue("phone"));
    assertNull(metaMap.getValue("phone.home"));
  }


  @Test
  void shouldMethodHasGetterReturnTrueWhenListElementSet() {
    List<Object> param1 = new ArrayList<>();
    param1.add("firstParam");
    param1.add(222);
    param1.add(new Date());

    Map<String, Object> parametersEmulation = new HashMap<>();
    parametersEmulation.put("param1", param1);
    parametersEmulation.put("filterParams", param1);

    MetaObject meta = SystemMetaObject.forObject(parametersEmulation);

    assertEquals(param1.get(0), meta.getValue("filterParams[0]"));
    assertEquals(param1.get(1), meta.getValue("filterParams[1]"));
    assertEquals(param1.get(2), meta.getValue("filterParams[2]"));

    assertTrue(meta.hasGetter("filterParams[0]"));
    assertTrue(meta.hasGetter("filterParams[1]"));
    assertTrue(meta.hasGetter("filterParams[2]"));
  }

}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值