MyBatis反射工具

ObjectFactory

ObjectFactory是MyBatis创建对象的基类,主要通过create创建对象,可以通过有参或者无参构造方法创建对象,此时的对象属性并没有初始化。

/**
   * 通过无参构造方法创建对象
   */
  <T> T create(Class<T> type);

  /**
   * 通过有参构造创建对象
   */
  <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);

ObjectFactory的默认实现是DefaultObjectFactory,最终通过instantiateClass方法创建对象:

  1. 判断是否存在无参构造函数,存在无参构造直接反射创建对象。

  2. 如果构造方法是私有的,通过反射修改访问限制,再创建对象。

  3. 无参构造创建失败,尝试通过有参构造创建对象。

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[constructorArgTypes.size()]));
      try {
        return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));
      } catch (IllegalAccessException e) {
        if (Reflector.canControlMemberAccessible()) {
          constructor.setAccessible(true);
          return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));
        } else {
          throw e;
        }
      }
    } catch (Exception e) {
      // ···
      throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);
    }
  }

ObjectWrapperFactory

ObjectWrapperFactory工厂是为了创建ObjectWrapper。

ObjectWrapper

ObjectWrapper主要分为两类,一种是我们普通的JavaBean(BeanWrapper),另一种主要就是集合类型(MapWrapper、CollectionWrapper)。ObjectWrapper就是代理对象,可以通过get\set方法给目标对象赋值、取值。

/**
   * 获得指定属性的值
   */
  Object get(PropertyTokenizer prop);

  /**
   * 设置指定属性的值
   */
  void set(PropertyTokenizer prop, Object value);

ReflectorFactory

创建Reflector的工厂类, Reflector是mybatis反射模块的基础,每个Reflector对象都对应一个类,在其中缓存了反射操作所需要的类元信息。

Reflector

reflector主要是为了创建pojo描述信息,类似于Spring中的BeanDefinition。

// 创建对象的类型
  private final Class<?> type;
  // get,is方法的属性
  private final String[] readablePropertyNames;
  // set,is方法的属性
  private final String[] writablePropertyNames;
  // 属性对应的set方法,key为属性名,Invoker
  private final Map<String, Invoker> setMethods = new HashMap<>();
  // 属性对应的get方法,key为属性名
  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<>();

reflector数据再构造方法中初始化。

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

MetaObject

MetaObject是对象元数据的封装。originalObject原生对象,objectWrapper是包装过得对象,通过objectWrapper可以对对象进行get\set操作。

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

PropertyTokenizer

属性解析,例如,user[1].linkman.name 被被解析成:

children=linkman.name
indexedName=user[1]
name=user
index=1

 // 当前表达式名称,属性名
 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); // a[0]
     children = fullname.substring(delim + 1); // b[0].c
   } else {
     name = fullname;
     children = null;
   }
   indexedName = name;  // a[0]
   delim = name.indexOf('[');
   if (delim > -1) {
     index = name.substring(delim + 1, name.length() - 1);  // 0
     name = name.substring(0, delim);  // a
   }
 }

对象创建流程演示

    @Test
    public void test(){
      //创建ObjectFactory工厂类
      ObjectFactory objectFactory = new DefaultObjectFactory();
      //获取实例化的目标对象
      User user = objectFactory.create(User.class);
      //创建ObjectWrapperFactory工厂类
      ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();
      //创建ReflectorFactory工厂类
      ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
      MetaObject metaObject = MetaObject.forObject(user, objectFactory, objectWrapperFactory, reflectorFactory);

      //使用反射工具类将行数据转换成POJO类
      BeanWrapper objectWrapper = (BeanWrapper) metaObject.getObjectWrapper();

      //模拟数据库行数据转化成对象
      //1.模拟从数据库读取数据
      Map<String, Object> dbResult = new HashMap<>();
      dbResult.put("id", 1);
      dbResult.put("name", "张三");
      //2.模拟映射关系
      Map<String, String> mapper = new HashMap<String, String>();
      mapper.put("id", "id");
      mapper.put("name", "name");

      Set<Map.Entry<String, String>> entrySet = mapper.entrySet();
      for (Map.Entry<String, String> colInfo : entrySet) {
        String propName = colInfo.getKey();
        Object propValue = dbResult.get(colInfo.getValue());
        PropertyTokenizer proTokenizer = new PropertyTokenizer(propName);
        objectWrapper.set(proTokenizer, propValue);
      }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值