Mybatis工具—反射工具(MetaObject)

  MetaObject是Mybatis中的反射工具类,其位于Mybatis源码包中的org.apache.ibatis.reflection。从MetaObject的命名和所处的位置不难看出,该类主要的工作就是获取和设置对象的属性值。

@Data
public class Robot{
    private String name;
}
    
Robot robot = new Robot();
// 使用SystemMetaObject类的静态方法forObject()构造MetaObject
MetaObject metaObject = SystemMetaObject.forObject(robot);
metaObject.setValue("name", "机器人0001");
Object value = metaObject.getValue("name");

  从上述示例代码可以看出,MetaObject类是使用SystemMetaObject类的静态方法forObject()来完成构造的,那么为什么要使用SystemMetaObject类的静态方法forObject()来构造呐?这里就不得不从MetaObject类的构造方法说起了。

构造方法

  MetaObject构造方法的源代码如下:

/**
 * @param object               原始对象
 * @param objectFactory        对象工厂
 * @param objectWrapperFactory 对象包装工厂
 * @param 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);
    }
 }

  从源代码可以看出MetaObject类的构造方法被改为了private私有域,这也是不能直接通过new MetaObject()来构造MetaObject对象的主要原因。通过观察MetaObject构造方法可以看出,如果想要构造一个MetaObject对象就除了提供想要操作的原始object以外,同时还要提供ObjectFactory、ObjectWrapperFactory和ReflectorFactory三个同样位于org.apache.ibatis.reflection包下的反射操作接口。

  • ObjectFactory

  ObjectFactory位于Mybatis源代码org.apache.ibatis.reflection.factory包中,从所处的包和命名不难看出,该接口的主要职责就是用来创建所需类的对象。其主要实现类DefaultObjectFactory实现了所需的所有方法。

  • ObjectWrapperFactory

  ObjectWrapperFactory位于Mybaits源代码org.apache.ibatis.reflection.wrapper包中,该接口主要的职责就是将某个对象包装成ObjectWrapper对象,其主要实现类DefaultObjectWrapperFactory提供了支持。

  • ReflectorFactory

  ReflectorFactory位于Mybatis源代码org.apache.ibatis.reflection包中,该接口的主要职责就是对目标对象进行反射操作提供能力,其主要实现类DefaultReflectorFactory提供了支持。
从MetaObject构造方法的源代码来看,其除了对Object object、ObjectFactory objectFactory、ObjectWrapperFactory objectWrapperFactory和ReflectorFactory reflectorFactory这个属性进行赋值以外,还通过判断目标对象object的对象属性来构造ObjectWrapper对象来作为整个反射操作后的承载。在构造ObjectWrapper对象的过程中,同时使用到了之前已经赋值好的objectFactory、objectWrapperFactory和reflectorFactory对象。

SystemMetaObject

  至此再来看下SystemMetaObject类中的静态方法forObject构造MetaObject对象的细节,SystemMetaObject源代码中定义了两个常量分别对应ObjectFactory和ObjectWrapperFactor,最终这两个常量会用于调用MetaObject.forObject()方法来构造MetaObject对象。
  从SystemMetaObject类中的静态方法forObject得出,最终还是调用了MetaObject.forObject()方法来构造MetaObject对象

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(
              new NullObject(), 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());
  }

}

MetaObject操作对象

  上述已经明白了MetaObject对象是如何构造而来的,并且从构造方法我们不难看出MetaObject类使用了组合模式,配合originalObject、objectWrapper、objectFactory、objectWrapperFactory和reflectorFactory五个属性对象来使得原始对象完成反射操作。

  1. Object getValue(String name),获取目标对象中某个属性对应的值。
  2. void setValue(String name, Object value),将值value赋值到目标对象的name属性中。
  3. boolean hasSetter(String name),判断目标对象name属相是否有setter方法。
  4. boolean hasGetter(String name),判断目标对象name属相是否有getter方法。

你可能感兴趣的:(mybatis,mybatis,java,开发语言)